将DataGrid嵌入到WPF Treeview节点中

5

我需要在树形视图中显示层次结构,但详细信息应该在数据网格中显示。

期望效果

我该如何编写模板以实现此目的?我现在对模板有所误解。

    <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>
1个回答

9
我找到了一个解决方法。我需要理解细节应该作为一个集合在一个具有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转换器,并在转换器参数中设置要返回的类型。

<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>

我已经将示例上传到Dropbox。 这是它的样子:

Treeview节点的DataGrid


@user575219 很高兴能帮到你。 - Artiom
好的!谢谢你的肯定 :) - Harxish
好的!谢谢你的支持 :) - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接