HierarchicalDataTemplate и HeaderedItemsControl с ControlTemplate не могут показать вложенные данные
Я могу заставить эту модель работать с Menu
а также TreeView
но я должен что-то упустить, когда я пытаюсь HeaderedItemsControl
:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<HierarchicalDataTemplate x:Key="MenuItemTemplate" ItemsSource="{Binding XPath=foo}">
<AccessText Text="{Binding XPath=@a}" />
</HierarchicalDataTemplate>
<Style TargetType="HeaderedItemsControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type HeaderedItemsControl}">
<StackPanel>
<ContentPresenter ContentSource="Header"/>
<ItemsPresenter Margin="10,0,0,0" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<XmlDataProvider x:Key="RootXml" XPath="/root/foo">
<x:XData>
<root xmlns="">
<foo a="one">
<foo a="two" b="wow, two" />
<foo a="three" b="wow, three" />
<foo a="four" b="wow, four" />
</foo>
<foo a="one again">
<foo a="two others" b="wow, two others" />
<foo a="three the hard way" b="wow, three again" />
</foo>
</root>
</x:XData>
</XmlDataProvider>
</Page.Resources>
<StackPanel>
<HeaderedItemsControl
Header="My Foo List"
ItemTemplate="{Binding Source={StaticResource MenuItemTemplate}}"
ItemsSource="{Binding Source={StaticResource RootXml}}">
</HeaderedItemsControl>
</StackPanel>
</Page>
В XamlPadX это показывает:
My foo list
one
one again
Нужно ли что-то делать с ControlTemplate
получить данные для корректного отображения? Или мне нужно более сложное (или дополнительное) HierarchicalDataTemplate
? Также: как мы показываем foo/@b
данные?
3 ответа
Вот поздний ответ. Я тоже пытался это выяснить, но не был удовлетворен рассуждениями в приведенном выше ответе и / или связанном ответе, поскольку шаблон XAML должен быть одинаковым для всех элементов управления.
После небольшого количества времени с jetbrains dotPeek и размышлениями о TreeView Control ответ, наконец, довольно прост. TreeView и TreeViewItem переопределяют IsItemItsOwnContainerOverride и GetContainerForItemOverride в элемент управления, который будет содержать дочерние элементы (TreeViewItem в случае TreeView). Вы можете создать два простых пользовательских элемента управления, чтобы справиться с этим.
Ваш класс HeaderedItemControl будет выглядеть примерно так:
public class MyHierarchicalViewItem : HeaderedItemsControl
{
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is MyHierarchicalViewItem;
}
protected override DependencyObject GetContainerForItemOverride()
{
return (DependencyObject)new MyHierarchicalViewItem();
}
}
Ваш ItemControl (эквивалентный TreeView или Menu) будет выглядеть так:
public class MyHierarchicalView:ItemsControl
{
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is MyHierarchicalViewItem;
}
protected override DependencyObject GetContainerForItemOverride()
{
return (DependencyObject) new MyHierarchicalViewItem();
}
}
Ваш XAML будет во многом таким же, просто поместив ссылку на правильный элемент управления и добавив соответствующее пространство имен (мой случай xmlns:myControls="clr-namespace:").
<UserControl.Resources>
<HierarchicalDataTemplate x:Key="MenuItemTemplate" ItemsSource="{Binding XPath=foo}">
<AccessText Text="{Binding XPath=@a}" />
</HierarchicalDataTemplate>
<Style TargetType="{x:Type myControls:MyHierarchicalViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type myControls:MyHierarchicalViewItem}">
<StackPanel>
<ContentPresenter ContentSource="Header"/>
<ItemsPresenter Margin="10,0,0,0" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<XmlDataProvider x:Key="RootXml" XPath="/root/foo">
<x:XData>
<root xmlns="">
<foo a="one">
<foo a="two" b="wow, two" />
<foo a="three" b="wow, three" />
<foo a="four" b="wow, four" />
</foo>
<foo a="one again">
<foo a="two others" b="wow, two others" />
<foo a="three the hard way" b="wow, three again" />
</foo>
</root>
</x:XData>
</XmlDataProvider>
</UserControl.Resources>
<StackPanel>
<myControls:MyHierarchicalViewItem
Header="My Foo List"
ItemTemplate="{Binding Source={StaticResource MenuItemTemplate}}"
ItemsSource="{Binding Source={StaticResource RootXml}}">
</myControls:MyHierarchicalViewItem>
</StackPanel>
</UserControl>
HierarchicalDataTemplate
предназначен для древовидных представлений с автоматическим расширением дочерних элементов. В вашем случае вы можете просто использовать обычный DataTemplate
,
Это похоже на сделку:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<XmlDataProvider x:Key="RootXml" XPath="/root/foo">
<x:XData>
<root xmlns="">
<foo a="one" b="test1">
<foo a="two" b="wow, two" />
<foo a="three" b="wow, three" />
<foo a="four" b="wow, four" />
</foo>
<foo a="one again" b="test2">
<foo a="two others" b="wow, two others" />
<foo a="three the hard way" b="wow, three again" />
</foo>
</root>
</x:XData>
</XmlDataProvider>
<Style TargetType="HeaderedItemsControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type HeaderedItemsControl}">
<StackPanel>
<ContentPresenter ContentSource="Header"/>
<ItemsPresenter Margin="10,0,0,0" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<HierarchicalDataTemplate x:Key="NestedFooItemTemplate">
<AccessText Text="{Binding XPath=@b}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="FooItemTemplate">
<StackPanel>
<AccessText Text="{Binding XPath=@a}" />
<HeaderedItemsControl
Header="My Nest"
ItemTemplate="{Binding Source={StaticResource NestedFooItemTemplate}}"
ItemsSource="{Binding XPath=./foo}"
Margin="10,0,0,0" />
</StackPanel>
</HierarchicalDataTemplate>
</Page.Resources>
<StackPanel>
<HeaderedItemsControl
Header="My Foo List"
ItemTemplate="{Binding Source={StaticResource FooItemTemplate}}"
ItemsSource="{Binding Source={StaticResource RootXml}}">
</HeaderedItemsControl>
</StackPanel>
</Page>