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>
Другие вопросы по тегам