2011-10-03 244 views
6

我想在TreeView中顯示任意的XML,並展開和摺疊節點,同時顯示元素名稱和屬性及其值的集合。我想我可以用HierarchicalDataTemplate來做到這一點。如何使用HierarchicalDataTemplate顯示XML元素和屬性?

我見過的提示使用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定義,我得到這個用於顯示:

enter image description here

不太我想要的。對於每個節點,我希望顯示元素名稱屬性及其值。

我嘗試這樣做:

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

...這讓我有點接近,但在TreeView的 Value="{Binding Path=Attributes}"結果 「(集合)」 的顯示。

enter image description here

我怎麼能簡單地顯示所有的實際屬性名稱和值,除了該元素的名稱?

+0

可以ü分享你最終的代碼嗎? (+1在那裏):) –

回答

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> 

現在,它顯示的元素名稱一組屬性和它們的值,如:

enter image description here

+0

它看起來正是我需要的。你能分享你的代碼嗎? –

+0

不幸的是沒有。當我的HD崩潰時,我的代碼丟失了。 – Cheeso

+0

很抱歉聽到它!最後我使用了WebBrowser.Navigate(「c:\ data.xml」)。所以對我來說沒關係!謝謝你的回答Cheeso! –

4

您還可以針對不同節點類型使用模板選擇器,並使用XPath節點()| @ *循環所有類型的節點:

<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)); 
    } 
}