2015-04-23 55 views
2

我有一个TreeView,我想绑定一些数据给它;我想为每种类型的数据显示不同的TreeViewItem布局,并看着this example我想出了如何做到这一点。WPF:如何将通用数据绑定到TreeView?

到目前为止,我有因此以下类:

public class Category 
{ 
    public string Name { get; set; } 
    public List<Product> Products { get; set; } 
} 
public class Product 
{ 
    public string Name { get; set; } 
} 

现在我需要使用包装这样的处理数据:

public class DataWrapper<T> where T : class 
{ 

    public T Data { get; set; } 
} 

而且我想设置的ItemSource为TreeView创建像这样的列表:

IList<DataWrapper<Category>> list = new List<DataWrapper<Category>>(); 

Category c = new Category() { Name = "C1", Products = new List<Product>() { new Product() { Name = "P1" }, new Product() { Name = "P2" } } }; 
list.Add(new DataWrapper<Category>() { Data = c }); 

c = new Category() { Name = "C2", Products = new List<Product>() { new Product() { Name = "P3" }, new Product() { Name = "P4" } } }; 
list.Add(new DataWrapper<Category>() { Data = c }); 

c = new Category() { Name = "C3", Products = new List<Product>() { new Product() { Name = "P5" }, new Product() { Name = "P6" } } }; 
list.Add(new DataWrapper<Category>() { Data = c }); 

所以我所做的就是将DataContext设置为treeVie女:

myTreeView.DataContext =list; 

,这是XAML:

<TreeView x:Name="myTreeView"> 
     <TreeView.Resources> 
      <HierarchicalDataTemplate DataType="{x:Type src:Category}" ItemsSource="{Binding Path=Data}"> 
       <StackPanel> 
        <TextBlock Text="Category:" /> 
        <TextBlock Text="{Binding Path=Name}" /> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
      <HierarchicalDataTemplate DataType="{x:Type src:Product}"> 
       <StackPanel> 
        <TextBlock Text="Product:" /> 
        <TextBlock Text="{Binding Path=Name}" /> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
     </TreeView.Resources> 
    </TreeView> 

但是,当然,它的工作不是:) 谁能exaplain我如何正确地绑定对象名单等?

谢谢

回答

2

它不工作的原因是你绑定ItemsSource到上DataContext这是List<DataWrapper<Category>>型的,不具有这种性质称为Data财产。

我不太清楚你需要什么包装。最简单的方法是摆脱包装纸,使列表项类型Category的列表,并使用该列表作为ItemsSource

IList<Category> list = new List<Category>(); 

Category c = new Category() { Name = "C1", Products = new List<Product>() { new Product() { Name = "P1" }, new Product() { Name = "P2" } } }; 
list.Add(c); 

... 

// Set this list as ItemsSource 
myTreeView.ItemsSource=list; 

那会做的,然后你的数据模板类型绑定将得到应用正确。

另外,如果您需要包装,只要包装非通用:

public class CategoryWrapper 
{ 
    public Category Data { get; set; } 
} 

和修改类别模板:

<HierarchicalDataTemplate DataType="{x:Type src:CategoryWrapper}" ItemsSource="{Binding Path=Data.Products}"> 
    <StackPanel> 
     <TextBlock Text="Category:" /> 
     <TextBlock Text="{Binding Path=Data.Name}" /> 
    </StackPanel> 
</HierarchicalDataTemplate> 

原因使得非通用,是指定泛型为模板的DataType并不容易:

<!-- Doesn't work! --> 
DataType="{x:Type src:DataWrapper<Category>}" 

希望这有助于!让我知道如果这种解决方案不适用于你的情况,我会再看看它...

+0

嗨马克, 感谢您的帮助,由于您的建议,我设法正确地绑定数据。特别是我使用了后一种解决方案,创建了一个非泛型包装器(尽管这在我的项目中添加了很多代码复制)。 我想给你更详细的解释,为什么我需要使用数据包装。我正在开发一个项目,在gui中显示的数据量非常大,我发现了一种使用虚拟化来优化加载操作的方法(查看[this](http://www.zagstudio.com) /blog/378#.VTpB5pMQuq9))。这个解决方案像DataGrid一样的魅力 – Mauri

+0

下一步是将这个“虚拟化”放在TreeView上。 不幸的是我发现这种方法似乎不被TreeView控件支持。事实上,DataGrid和TreeView之间的巨大差异在于,DataGrid只在要显示元素时访问绑定集合的元素,而TreeView在首次访问时加载所有元素。 – Mauri