2015-04-23 75 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