How can I use HierarchicalDataTemplate to display XML Elements and Attributes?
I added an ItemsControl
into the template, like this :
<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="="" Foreground="{StaticResource xmlMarkBrush}"/> <TextBlock Text="{Binding Path=Value}" Foreground="{StaticResource xmlValueBrush}"/> <TextBlock Text=""" 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 element names and the set of attributes and their values, like this:
you also can use a template selector for the different node types and use the XPath node()|@* to loop thru 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)); }}