wpf datagrid treeview datatemplate hierarchicaldatatemplate

Incruste DataGrid en nodos WPF Treeview



datatemplate hierarchicaldatatemplate (1)

Necesito mostrar Hierarchy en la vista de árbol . Pero los detalles deben mostrarse en la cuadrícula de datos .

¿Cómo debo escribir mi plantilla para lograr esto? No entiendo muy bien las plantillas por ahora.

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


Encontré una solución. Tenía que entender que los Detalles deberían presentarse como una colección dentro de un único elemento que tiene la propiedad IEnumerable. Puede ser que no sea la mejor solución, pero funciona.

Necesitaba crear un convertidor para envolver mi colección en una sola.

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(); } }

Ejemplo para envoltorios:

internal interface IItemsWrapper { IEnumerable Items { get; set; } } public class ItemsWrapper : IItemsWrapper { public IEnumerable Items { get; set; } } public class DetailItemsWrapper : ItemsWrapper{} public class InvoiceItemsWrapper:ItemsWrapper{}

Y el xaml. No requerirá muchos cambios. Solo necesita usar el convertidor de Boxeo y establecer el Tipo para regresar en el parámetro del convertidor.

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

Subí la muestra a Dropbox. Así es como se ve: