How can I use the HierarchicalDataTemplate to display XML elements and attributes?

I would like to display arbitrary XML in a TreeView with extension and collapse of nodes, displaying both the name of the element and the set of attributes and their values. I think I can do this with the HierarchicalDataTemplate.

I saw tips for using the HierarchicalDataTemplate to display arbitrary XML elements and text nodes, for example:

<Window.Resources> <HierarchicalDataTemplate x:Key="NodeTemplate"> <TextBlock x:Name="tbName" Text="?" /> <HierarchicalDataTemplate.ItemsSource> <Binding XPath="child::node()" /> </HierarchicalDataTemplate.ItemsSource> <HierarchicalDataTemplate.Triggers> <DataTrigger Binding="{Binding Path=NodeType}" Value="Text"> <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Value}"/> </DataTrigger> <DataTrigger Binding="{Binding Path=NodeType}" Value="Element"> <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Name}"/> </DataTrigger> </HierarchicalDataTemplate.Triggers> </HierarchicalDataTemplate> <XmlDataProvider x:Key="xmlDataProvider"> </XmlDataProvider> </Window.Resources> .... <TreeView Name="treeView1" ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}" ItemTemplate= "{StaticResource NodeTemplate}"/> 

Which works great. It displays element names and text for each element. But my XML uses attributes to carry information. The schema is complex and I donโ€™t have a formal definition for it, so I consider it as arbitrary XML.

The simplest document is as follows:

 <c4soap name="GetVersionInfo" seq="" result="1"> <versions> <version name="Director" version="2.1.0.126418" buildtype="" builddate="Jun 1 2011" buildtime="14:52:43" /> <version name="MediaManager" version="2.1.0.126418" buildtype="" builddate="Jun 1 2011" buildtime="14:36:17" /> </versions> </c4soap> 

Using the above definition of HierarchicalDataTemplate, I get this for display:

enter image description here

Not quite what I want. For each node, I want to display both the name of the element and a set of attributes and their values.

I tried this:

  <Window.Resources> <HierarchicalDataTemplate x:Key="NodeTemplate"> <WrapPanel Focusable="False"> <TextBlock x:Name="tbName" Text="?" /> <TextBlock x:Name="tbAttrs" Text="?" /> </WrapPanel> <HierarchicalDataTemplate.ItemsSource> <Binding XPath="child::node()" /> </HierarchicalDataTemplate.ItemsSource> <HierarchicalDataTemplate.Triggers> <DataTrigger Binding="{Binding Path=NodeType}" Value="Text"> <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Value}"/> </DataTrigger> <DataTrigger Binding="{Binding Path=NodeType}" Value="Element"> <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Name}"/> <Setter TargetName="tbAttrs" Property="Text" Value="{Binding Path=Attributes}"/> </DataTrigger> </HierarchicalDataTemplate.Triggers> </HierarchicalDataTemplate> <XmlDataProvider x:Key="xmlDataProvider"> </XmlDataProvider> </Window.Resources> 

... which brings me a little closer, but Value="{Binding Path=Attributes}" leads to displaying "(Collection)" in the TreeView.

enter image description here

How can I just display all the actual names and attribute values โ€‹โ€‹in addition to the element name?

+6
source share
2 answers

I added an ItemsControl to the template, for example:

 <Window.Resources> <SolidColorBrush x:Key="xmlValueBrush" Color="Blue" /> <SolidColorBrush x:Key="xmAttributeBrush" Color="Red" /> <SolidColorBrush x:Key="xmlTagBrush" Color="DarkMagenta" /> <SolidColorBrush x:Key="xmlMarkBrush" Color="Blue" /> <DataTemplate x:Key="attributeTemplate"> <StackPanel Orientation="Horizontal" Margin="3,0,0,0" HorizontalAlignment="Center"> <TextBlock Text="{Binding Path=Name}" Foreground="{StaticResource xmAttributeBrush}"/> <TextBlock Text="=&quot;" Foreground="{StaticResource xmlMarkBrush}"/> <TextBlock Text="{Binding Path=Value}" Foreground="{StaticResource xmlValueBrush}"/> <TextBlock Text="&quot;" Foreground="{StaticResource xmlMarkBrush}"/> </StackPanel> </DataTemplate> <HierarchicalDataTemplate x:Key="nodeTemplate"> <StackPanel Orientation="Horizontal" Focusable="False"> <TextBlock x:Name="tbName" Text="?" /> <ItemsControl ItemTemplate="{StaticResource attributeTemplate}" ItemsSource="{Binding Path=Attributes}" HorizontalAlignment="Center"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </StackPanel> <HierarchicalDataTemplate.ItemsSource> <Binding XPath="child::node()" /> </HierarchicalDataTemplate.ItemsSource> <HierarchicalDataTemplate.Triggers> <DataTrigger Binding="{Binding Path=NodeType}" Value="Text"> <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Value}"/> </DataTrigger> <DataTrigger Binding="{Binding Path=NodeType}" Value="Element"> <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Name}"/> </DataTrigger> </HierarchicalDataTemplate.Triggers> </HierarchicalDataTemplate> <XmlDataProvider x:Key="xmlDataProvider"> </XmlDataProvider> </Window.Resources> 

Now it displays the names of the elements and a set of attributes and their values, for example:

enter image description here

+9
source

you can also use the template selector for different types of node and use XPath node () | @ * for a loop through all types of nodes:

 <TreeView x:Name="TreeView" ItemsSource="{Binding}" ItemTemplateSelector="{DynamicResource ResourceKey=NodeTemplateSelector}"> <TreeView.Resources> <HierarchicalDataTemplate x:Key="TextTemplate"> <Grid> <uixml:TextInputControl DataContext="{Binding}" /> </Grid> </HierarchicalDataTemplate> <HierarchicalDataTemplate x:Key="AttributeTemplate"> <Grid> <uixml:AttributeInputControl DataContext="{Binding}" /> </Grid> </HierarchicalDataTemplate> <HierarchicalDataTemplate x:Key="NodeTemplate" > <TextBlock Text="{Binding Path=Name}" /> <HierarchicalDataTemplate.ItemsSource> <Binding XPath="child::node()|@*" /> </HierarchicalDataTemplate.ItemsSource> </HierarchicalDataTemplate> <ui:XmlTemplateSelector x:Key="NodeTemplateSelector" NodeTemplate="{StaticResource NodeTemplate}" TextTemplate="{StaticResource TextTemplate}" AttributeTemplate="{StaticResource AttributeTemplate}" /> </TreeView.Resources> </TreeView> 

and:

 public class XmlTemplateSelector:DataTemplateSelector{ public DataTemplate NodeTemplate { get; set; } public DataTemplate TextTemplate { get; set; } public DataTemplate AttributeTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { XmlNode node = (XmlNode)item; switch (node.NodeType) { case XmlNodeType.Attribute: return AttributeTemplate; case XmlNodeType.Element: return NodeTemplate; case XmlNodeType.Text: return TextTemplate; } throw new NotImplementedException(String.Format("not implemented for type {0}", node.NodeType)); } } 
+4
source

Source: https://habr.com/ru/post/898521/


All Articles