Привязка данных XML к TreeView с дочерними узлами разных типов под одним родителем - PullRequest
2 голосов
/ 29 октября 2010

Примечание. Решение см. В нижней части этого поста.

Я пытаюсь использовать «HierarchicalDataTemplate» XAML для отображения XML-документа в TreeView.Мой текущий код XAML будет отображать первый дочерний узел «Parent», но не последующие дочерние узлы разных типов.

Могу ли я использовать XAML для отображения дочерних элементов разных типов под общим родителем?

Я свел проблему к очень простому образцу в иллюстративных целях.

Я хочу, чтобы мое древовидное представление выглядело так (за исключением содержимого в скобках):

Parent: Roger (Type="Parent")
 |--Rug rats (Type="Children")
 |     |--Bob (Type="Child")
 |     |--Tom
 |
 |--Gear (Type="Equipment")  <-- **can't display this or its child nodes**
       |--Canoe (Type="Item")
       |--Tent

В этом примере у «родительских» узлов есть 2 типа дочерних узлов;«Дети» и «Оборудование».

Вот XML:

<Parent Name="Roger">
   <Children>
     <Child Name="Bob"/>
     <Child Name="Tom"/>
  </Children>
  <EquipmentList>
     <Item Name="Canoe"/>
     <Item Name="Tent"/>
   </EquipmentList>
</Parent>

Вот шаблоны данных XAML для визуализации узлов дерева:

<Window.Resources>
    <HierarchicalDataTemplate DataType="Parent" ItemsSource="{Binding XPath=Children}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text=": "/>
            <TextBlock Text="{Binding XPath=@Name, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate DataType="Children" ItemsSource="{Binding XPath=Child}">
        <TextBox Width="Auto" Text="Rug Rats" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate DataType="Child">
        <TextBox Width="Auto" Text="{Binding XPath=@Name, UpdateSourceTrigger=PropertyChanged}" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate DataType="EquipmentList" ItemsSource="{Binding XPath=Item}">
        <TextBox Width="Auto" Text="Gear" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate DataType="Item">
        <TextBox Width="Auto" Text="{Binding XPath=@Name, UpdateSourceTrigger=PropertyChanged}" />
    </HierarchicalDataTemplate>

</Window.Resources>

В интересахдля полноты, вот код, который заполняет дерево:

_xmlDoc = new XmlDocument();
_xmlDoc.Load(@"..\..\SampleXMLFile.xml");

treeViewToolDescription.ItemsSource = _xmlDoc;

Я уже несколько дней гуглюл комбинации "XML", "TreeView", "HierarchicalDataTemplate" и "разнородный", такЯ видел (но явно не понял) довольно много статей, которые выглядели многообещающими, но никогда не казались достаточно уместными.

РЕШЕНИЕ

Решениебыло использовать звездочку для ItemsSource, чтобы получить все дочерние элементы независимо от типа, т.е. ItemsSource = "{Binding XPath = *}"

До (ItemsSource явно установил тип "Children"):

    <HierarchicalDataTemplate DataType="Parent" ItemsSource="{Binding XPath=Children}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Parent: "/>
            <TextBlock Text="{Binding XPath=@Name, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
    </HierarchicalDataTemplate>

После (ItemsSource установлен на "*" вместо указания типа):

    <HierarchicalDataTemplate DataType="Parent" ItemsSource="{Binding XPath=*}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Parent: "/>
            <TextBlock Text="{Binding XPath=@Name, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
    </HierarchicalDataTemplate>

1 Ответ

2 голосов
/ 29 октября 2010

Короткий ответ: ты не можешь в том виде, в каком он есть. Вам нужно создать одно свойство, которое объединит все дочерние элементы данного узла в одно свойство.

Так что в этом случае вам нужно свойство SubNodes, подобное следующему

Parent.SubNodes => a list {Rug Rats, Gear}
Children.SubNodes for Rug Rats=> a list {Bob, Tom} 
Equipment.SubNodes for Gear => a list {Canoe, Tent} Items

и вы можете использовать DataTemplates для каждого типа, чтобы визуализировать внешний вид каждого конечного узла. Аналогичный вопрос WPF TreeView HierarchicalDataTemplate - привязка к объекту с несколькими дочерними коллекциями

...