6

我想在 TreeView 中显示任意 XML,带有展开和折叠节点,同时显示元素名称和属性集及其值。我想我可以用 HierarchicalDataTemplate 做到这一点。

我已经看到了使用 HierarchicalDataTemplate 来显示任意 XML元素和文本节点的提示,如下所示:

  <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}"/>

效果很好。它显示每个元素的元素名称和文本。但是我的 XML 使用属性来携带信息。模式很复杂,我没有正式的定义,所以现在我将其视为任意 XML。

最简单的文档如下所示:

<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>

使用上面的 HierarchicalDataTemplate 定义,我得到了这个显示:

在此处输入图像描述

不是我想要的。对于每个节点,我想同时显示元素名称属性集及其值。

我试过这个:

  <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>

...这让我有点接近,但 Value="{Binding Path=Attributes}"结果是在 TreeView 中显示“(集合)”。

在此处输入图像描述

除了元素名称之外,我如何才能简单地显示所有实际的属性名称和值?

4

2 回答 2

9

ItemsControl在模板中添加了一个,如下所示:

<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>

现在它显示元素名称属性集及其值,如下所示:

在此处输入图像描述

于 2011-10-03T14:39:03.793 回答
4

您还可以为不同的节点类型使用模板选择器,并使用 XPath node()|@* 循环遍历所有类型的节点:

<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>

和 :

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));
    }
}
于 2011-10-06T23:36:53.883 回答