2010-02-19 131 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