4

我需要在树视图中显示层次结构。但详细信息应显示在datagrid中。

我希望它是怎样的

我如何编写模板来实现这一点?我现在对模板有误解。

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

1 回答 1

8

我找到了解决方法。我必须明白,Details 应该作为具有 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

于 2012-08-14T08:52:01.583 回答