4

treeviewに Hierarchy を表示する必要があります。ただし、詳細はdatagridに表示する必要があります。

どのようになりたいか

これを達成するには、どのようにテンプレートを作成する必要がありますか? 今のところ、テンプレートのsmthを誤解しています。

    <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 コンバーターを使用し、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>

サンプルをドロップボックスにアップロードしました。これがどのように見えるかです:

TreeView ノードの DataGrid

于 2012-08-14T08:52:01.583 に答える