2009-05-07 20 views
7

Chciałbym powiązać dowolny dokument XML z WPF TreeView za pomocą TypeConverter.Powiąż dowolny dokument XML z WPF TreeView

Moim oryginalnym rozwiązaniem było użycie rekursji, ale gdy dokument jest duży, interfejs użytkownika jest mocno związany.

poniższy link rozmów o TypeConverter ale dla konkretnej kombinacji węzeł/elementu: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/edd843b7-b378-4c2d-926f-c053dbd7b340

Co zrobić, jeśli nie wiadomo, co dokument XML wygląda? Ponieważ jest to tylko w celach wyświetlania, nie interesuje mnie funkcjonalność w tym momencie, chcę tylko powiązać XML z TreeView.

Odpowiedz

3

Więc zadałem pytanie, jak powiązać dowolny dokument XML niezależnie od schematu do widoku drzewa w następujący sposób: 1. Powiązać dokument XML z WPF TreeView za pośrednictwem dostawcy XML i HierarchicalDataTemplate. 2. Wyświetl wszystkie węzły dokumentu XML, w tym te, które mają węzły potomne w następującym formacie:

> węźle Node1

node1 treści

>ChildNode1 

     ChildNode1 Contents 

      >ChildNode1'sChildNode 

       ChildNode1'sChildNode Contents 

> Node2

Node2 Contents 

Problem był że mój TreeView wiąże każdą właściwość nazwy XmlNode z TreeItem. W przypadku tekstu XmlNode wiązałby #text do TreeItem, który nie był tym, czego chciałem.

Więc poprzez post na forum MSDN dostałem odpowiedź: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/cbdb2420-1403-436f-aa7f-b1e3b1acb398/

Więc trik był w użyciu wyzwalaczy, aby ustawić wartość na podstawie typu węzła spotkaliśmy.

Uwaga: inne rodzaje węzłów będą ignorowane, a dokument XML może zawierać różne elementy, więc może nie działać dla każdego napotkanego typu węzła.

Oto XAML:

<Window x:Class="WpfApplication1.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1" 
    Title="Window1" Height="250" Width="450"> 

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

<Grid > 
    <TreeView Name="treeView1" 
       Background="AliceBlue" 
       ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}" 
       ItemTemplate= "{StaticResource NodeTemplate}"/> 
</Grid> 

public Window1() 
{ 
InitializeComponent(); 
XmlDataProvider dataProvider = this.FindResource("xmlDataProvider") as XmlDataProvider; 
     XmlDocument doc = new XmlDocument(); 
      // Testdocument  doc.LoadXml(
      @"<root> 
       <child1>text1<child11>text11</child11> 
       </child1> 
       <child2>text2<child21>text21</child21> 
        <child22>text22</child22> 
       </child2> 
       </root>"); 
     dataProvider.Document = doc; 
    } 
6

To działa dla innych typów węzłów za pomocą kilku prostych modyfikacji. Najpierw należy zmienić XPath HierarchicalDataTemplate.ItemsSource Binding na "child :: node() | atrybut :: *", aby zezwolić na dowolny węzeł podrzędny i dowolny atrybut. Następnie dodaj funkcję DataTriggers dla innych typów NodeTypes. Poniższy przykład pracował dla mnie. Zauważ, że dodany ikon dla różnych NodeTypes, można je usunąć:

 <HierarchicalDataTemplate x:Key="NodeTemplate"> 
     <StackPanel Orientation="Horizontal"> 
     <Image x:Name="icon" VerticalAlignment="Center" Margin="1,1,4,1"/> 
     <TextBlock x:Name="name" Text="" /> 
     <TextBlock x:Name="inter" Text="" /> 
     <TextBlock x:Name="value" Text="" /> 
     </StackPanel> 
     <HierarchicalDataTemplate.ItemsSource> 
      <Binding XPath="child::node()|attribute::*" /> 
     </HierarchicalDataTemplate.ItemsSource> 
     <HierarchicalDataTemplate.Triggers> 
      <DataTrigger Binding="{Binding Path=NodeType}" Value="Element"> 
       <Setter TargetName="icon" Property="Source" Value="icons/element.png"></Setter> 
       <Setter TargetName="name" Property="Text" Value="{Binding Path=Name}"></Setter> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=NodeType}" Value="Text"> 
       <Setter TargetName="icon" Property="Source" Value="icons/text.png"></Setter> 
       <Setter TargetName="value" Property="Text" Value="{Binding Path=Value}"></Setter> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=NodeType}" Value="Attribute"> 
       <Setter TargetName="icon" Property="Source" Value="icons/attribute.png"></Setter> 
       <Setter TargetName="name" Property="Text" Value="{Binding Path=Name}"></Setter> 
       <Setter TargetName="inter" Property="Text" Value=": "></Setter> 
       <Setter TargetName="value" Property="Text" Value="{Binding Path=Value}"></Setter> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=NodeType}" Value="CDATA"> 
       <Setter TargetName="icon" Property="Source" Value="icons/cdata.png"></Setter> 
       <Setter TargetName="value" Property="Text" Value="{Binding Path=Value}"></Setter> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=NodeType}" Value="Comment"> 
       <Setter TargetName="icon" Property="Source" Value="icons/comment.png"></Setter> 
       <Setter TargetName="value" Property="Text" Value="{Binding Path=Value}"></Setter> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=NodeType}" Value="ProcessingInstruction"> 
       <Setter TargetName="icon" Property="Source" Value="icons/pi.png"></Setter> 
       <Setter TargetName="value" Property="Text" Value="{Binding Path=Value}"></Setter> 
      </DataTrigger> 
     </HierarchicalDataTemplate.Triggers> 
    </HierarchicalDataTemplate> 
1

Wystarczy popatrzeć na moją odpowiedź na wątku - Binding XML data to WPF treeview Control Wierzę, że to jest dokładnie to, czego szukasz for.The odnośnik w wątek wskazuje na wpis, który daje przykład krok po kroku z opcją pobrania kodu źródłowego. Przykład jest napisany w taki sposób, aby związać dowolny dokument XML z widokiem drzewa WPF