2010-02-19 97 views
3

我試圖使用數據模板將集合綁定到wpf TreeView控件。集合中的每個項目(人員)還包含兩種不同類型的汽車和書籍的集合(汽車,書籍)。WPF TreeView HierarchicalDataTemplate - 綁定到具有不同子集合的對象

下面是節省空間所涉及對象的簡化列表。

public class Person 
{ 
    public string Name 
    public List<Book> Books; 
    public List<Car> Cars; 
} 

public class Book 
{ 
    public string Title 
    public string Author 
} 

public class Car 
{ 
    public string Manufacturer; 
    public string Model; 
} 

這裏是我如何結合

public MainWindow() 
    { 
     InitializeComponent(); 

     this.treeView1.ItemsSource = this.PersonList(); 
    } 

    public List<Person> PersonList() 
    { 
     List<Person> list = new List<Person>(); 


     Book eco = new Book { Title = "Economics 101", Author = "Adam Smith"}; 
     Book design = new Book { Title = "Web Design", Author = "Robins" }; 

     Car corola = new Car { Manufacturer = "Toyota", Model = "2005 Corola"}; 
     Car ford = new Car { Manufacturer = "Ford", Model = "2008 Focus"}; 

     Person john = new Person { Name = "John", Books = new ObservableCollection<Book> { eco, design }, Cars = new ObservableCollection<Car> { corola } }; 

     Person smith = new Person { Name = "Smith", Books = new ObservableCollection<Book> { eco, design }, Cars = new ObservableCollection<Car> { ford } }; 

     list.AddRange(new[] {john, smith }); 
     return list; 
    } 

這裏是XAML代碼

<Grid> 
    <TreeView Name="treeView1"> 
    </TreeView> 
</Grid> 

我期待看到樹的顯示這個樣子。

>John 
    >Books 
    Economics 101 : Adam Smith 
    Web Design : Robins 
    >Cars 
    Totota : 2005 Corola 
>Smith 
    >Books 
    Economics 101 : Adam Smith 
    Web Design : Robins 
    >Cars 
    Ford: 2008 Focus 

此標誌>用於顯示樹文件夾,不應在模板中考慮。

回答

7

這有點複雜,因爲你的樹有兩個不同的子集合。 WPF不支持多個ItemsSource定義的方案。因此,您需要將這些集合合併到一個CompositeCollection。複合元素(即Car,Book)的類型匹配將自動完成。

在XAML中,您需要定義與您的類型定義相匹配的所謂HierarchicalDataTemplates。如果local點到BookCarPerson定義的namepace,簡化HierarchicalDataTemplates看起來是這樣的:

<HierarchicalDataTemplate DataType="{x:Type local:Person}" 
           ItemsSource="{Binding CompositeChildren}"> 
     <TextBlock Text="{Binding Path=Name}" /> 
    </HierarchicalDataTemplate> 

    <HierarchicalDataTemplate DataType="{x:Type local:Book}"> 
     <TextBlock Text="{Binding Path=Title}" /> 
     <!-- ... --> 
    </HierarchicalDataTemplate> 

    <HierarchicalDataTemplate DataType="{x:Type local:Car}"> 
     <TextBlock Text="{Binding Path=Model}" /> 
     <!-- ... --> 
    </HierarchicalDataTemplate> 

然後,你需要到您的收藏掛接到樹控件。有幾個可能性要做到這一點,最簡單的將是你的Window類來定義屬性並定義綁定:

<TreeView Items={Binding ElementName=myWindow, Path=Persons}/> 

這應該指向你到正確的方向發展,但不要把我的代碼編譯就緒:-)

1

您需要一個DataTemplate,否則WPF不知道如何顯示您的對象。

+1

你可以幫助我與溫度設計? – Jama 2010-02-19 19:27:24

+0

約翰 書籍 經濟學101:亞當·斯密 網頁設計:羅賓斯 汽車 託託塔:2005 Corola 史密斯 書籍 經濟學101:亞當·斯密 網頁設計:羅賓斯 汽車 福特:2008年福克斯 – Jama 2010-02-19 19:29:22

3

CompositeCollection是一個很好的答案,除非您不能將子集合綁定到DataContext,因爲它不是Freezable。您只能將它們綁定到資源。 (有關更多信息,請參見this question)。由於ItemsSource中的ItemsSource需要綁定到當前上下文中的某個屬性纔有用,所以這在HierarchicalDataTemplate中很難使用。

如果您不需要在集合更改通知,您可以輕鬆地實現您的視圖模型的屬性,如:

public IEnumerable<object> Items 
{ 
    get { return Books.Concat(Cars); } 
} 

如果需要改變對收集的通知,這是少了很多瑣碎的。

+0

正如我的實體基礎在XSD上,我無法真正創建CompositeCollection。但是從XSD生成的代碼是部分的,所以我可以插入一個IEnumerable! – Kolky 2011-11-02 13:19:56