2012-08-13 195 views
4

我需要在樹形視圖中顯示層次結構。但詳細信息應顯示在數據網格中。將DataGrid嵌入到WPF Treeview節點

How I'd like it to be

如何我都要寫我的模板來實現這一目標?我現在誤解了模板中的錯誤。

<TreeView ItemsSource="{Binding Path=Categories}"> 
     <TreeView.Resources> 
      <HierarchicalDataTemplate DataType="{x:Type stackProjects:Category}" ItemsSource="{Binding Path=SubCategories}"> 
       <TextBlock Margin="3" Text="{Binding Path=CategoryName}"/> 
      </HierarchicalDataTemplate> 

      <HierarchicalDataTemplate DataType="{x:Type stackProjects:SubCategory}" ItemsSource="{Binding Path=Details}"> 
       <TextBlock Text="{Binding Path=SubCategoryName}"/> 
      </HierarchicalDataTemplate> 

      <DataTemplate DataType="{x:Type stackProjects:Detail}" > 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Margin="3" Text="{Binding Path=Name}"/> 
        <TextBlock Margin="3" Text=" - "/> 
        <TextBlock Margin="3" Text="{Binding Path=Info}"/> 
       </StackPanel> 
      </DataTemplate> 
     </TreeView.Resources> 
    </TreeView> 

回答

8

我找到了解決方法。我不得不明白,細節應該在具有IEnumerable屬性的單個元素中呈現爲集合。可能這不是最好的解決方案,但它的工作原理。

我需要創建一個轉換器來將我的集合包裝爲一個。

用於包裝
public class BoxingItemsConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var values = value as IEnumerable; 
     var type = parameter as Type; 

     if (values == null || type == null) 
      return null; 

     if (type.GetInterfaces().Any(x => x == typeof (IItemsWrapper))) 
     { 
      var instance = (IItemsWrapper) type.Assembly.CreateInstance(type.FullName); 
      instance.Items = (IEnumerable) value; 
      //returned value should be IEnumerable with one element. 
      //Otherwise we will not see children nodes 
      return new List<IItemsWrapper> {instance}; 
     } 
     return null; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

實施例:

internal interface IItemsWrapper 
{ 
    IEnumerable Items { get; set; } 
} 

public class ItemsWrapper : IItemsWrapper 
{ 
    public IEnumerable Items { get; set; } 
} 

public class DetailItemsWrapper : ItemsWrapper{} 

public class InvoiceItemsWrapper:ItemsWrapper{} 

而XAML。它不會需要很多更改。您只需使用Boxing轉換器並將Type設置爲在轉換器參數中返回。

<TreeView ItemsSource="{Binding Path=Categories}"> 
    <TreeView.Resources> 
     <HierarchicalDataTemplate DataType="{x:Type wpfProj:Category}" ItemsSource="{Binding Path=SubCategories}"> 
      <TextBlock Margin="4" Text="{Binding Path=CategoryName}"/> 
     </HierarchicalDataTemplate> 

     <HierarchicalDataTemplate DataType="{x:Type wpfProj:SubCategory}" 
            ItemsSource="{Binding Path=Details, Converter={StaticResource boxingItems}, ConverterParameter={x:Type wpfProj:DetailItemsWrapper}}" > 
      <StackPanel> 
       <TextBlock Margin="4" Text="{Binding Path=SubCategoryName}"/> 
      </StackPanel> 
     </HierarchicalDataTemplate> 

     <DataTemplate DataType="{x:Type wpfProj:DetailItemsWrapper}" > 
      <DataGrid ItemsSource="{Binding Path=Items}"/> 
     </DataTemplate> 
    </TreeView.Resources> 
</TreeView> 

我已經將sample上傳到了保管箱。 這裏是它如何看起來像:

DataGrid for TreeView nodes

+0

我不知道怎麼感謝你夠本。 – user575219 2016-09-29 03:16:33

+0

@ user575219我很高興它有幫助。 – Artiom 2016-09-29 07:49:35