2012-08-13 215 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