2011-10-03 8 views
6

Mi piacerebbe visualizzare l'XML arbitrario in un TreeView, con nodi espandibili e collassabili, mostrando sia il nome dell'elemento che l'insieme di attributi e i loro valori. Penso di poterlo fare con HierarchicalDataTemplate.Come posso utilizzare HierarchicalDataTemplate per visualizzare gli elementi e gli attributi XML?

Ho visto i suggerimenti per utilizzare HierarchicalDataTemplate per visualizzare XML arbitrario elementi, e nodi di testo, come questo:

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

Il che funziona alla grande. Visualizza i nomi degli elementi e il testo per ciascun elemento. Ma il mio XML utilizza attributi per trasportare informazioni. Lo schema è complesso e non ho una definizione formale di esso, quindi per ora lo sto trattando come XML arbitrario.

Il documento più semplice è simile al seguente:

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

Usando la definizione HierarchicalDataTemplate sopra, ottengo questo per una visualizzazione:

enter image description here

Non è proprio quello che voglio. Per ciascun nodo, desidero visualizzare sia il nome dell'elemento e l'insieme di attributi e i relativi valori.

ho provato questo:

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

... che mi fa un pò stretta, ma i Value="{Binding Path=Attributes}" risultati in un display di "(Collection)" nel controllo TreeView.

enter image description here

Come posso semplicemente visualizzare tutti i nomi degli attributi reali e valori, oltre al nome dell'elemento?

+0

U potrebbe condividere codice finale per favore? (+1 c'è) :) –

risposta

9

ho aggiunto un ItemsControl nel modello, in questo modo:

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

Ora visualizza i nomi degli elementi e l'insieme di attributi ei loro valori, in questo modo:

enter image description here

+0

Sembra esattamente quello di cui ho bisogno. Potresti condividere il tuo codice per favore? –

+0

sfortunatamente no. Il mio codice è stato perso quando il mio HD si è bloccato. – Cheeso

+0

Siamo spiacenti di sentirlo! Finalmente ho usato WebBrowser.Navigate ("c: \ data.xml"). Quindi va bene per me !. E grazie per la risposta Cheeso !! –

4

è anche possibile utilizzare un selettore di modelli per i diversi tipi di nodo e utilizzare il nodo XPath() | @ * per eseguire il ciclo su tutti i tipi di nodi:

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

e:

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