2008-10-09 157 views
4

我正在嘗試用表單層的WPF重寫我的ForestPad應用程序。在WinForms中,我以編程方式填充每個節點,但如果可能的話,我想利用WPF的數據綁定功能。Xml數據與WPF TreeView的雙向綁定

一般來說,雙向數據綁定WPF TreeView到一個Xml文檔的最佳方式是什麼?

一個通用的解決方案是好的,但參考,我試圖綁定到看起來像這樣的XML文檔的結構:

<?xml version="1.0" encoding="utf-8"?> 
<forestPad 
    guid="6c9325de-dfbe-4878-9d91-1a9f1a7696b0" 
    created="5/14/2004 1:05:10 AM" 
    updated="5/14/2004 1:07:41 AM"> 
<forest 
    name="A forest node" 
    guid="b441a196-7468-47c8-a010-7ff83429a37b" 
    created="01/01/2003 1:00:00 AM" 
    updated="5/14/2004 1:06:15 AM"> 
    <data> 
    <![CDATA[A forest node 
     This is the text of the forest node.]]> 
    </data> 
    <tree 
     name="A tree node" 
     guid="768eae66-e9df-4999-b950-01fa9be1a5cf" 
     created="5/14/2004 1:05:38 AM" 
     updated="5/14/2004 1:06:11 AM"> 
     <data> 
     <![CDATA[A tree node 
      This is the text of the tree node.]]> 
     </data> 
     <branch 
      name="A branch node" 
      guid="be4b0993-d4e4-4249-8aa5-fa9c940ae2be" 
      created="5/14/2004 1:06:00 AM" 
      updated="5/14/2004 1:06:24 AM"> 
      <data> 
      <![CDATA[A branch node 
       This is the text of the branch node.]]></data> 
       <leaf 
       name="A leaf node" 
       guid="9c76ff4e-3ae2-450e-b1d2-232b687214aa" 
       created="5/14/2004 1:06:26 AM" 
       updated="5/14/2004 1:06:38 AM"> 
       <data> 
       <![CDATA[A leaf node 
        This is the text of the leaf node.]]> 
       </data> 
      </leaf> 
     </branch> 
    </tree> 
</forest> 
</forestPad> 

回答

7

好吧,那就如果你的元素層次更像是更容易...

<node type="forest"> 
    <node type="tree"> 
     ... 

...而不是您當前的模式。

原樣,則需要4個HierarchicalDataTemplate S,一個包括根各層次元素,以及一個用於DataTemplate元素leaf

<Window.Resources> 
    <HierarchicalDataTemplate 
     DataType="forestPad" 
     ItemsSource="{Binding XPath=forest}"> 
     <TextBlock 
      Text="a forestpad" /> 
    </HierarchicalDataTemplate> 
    <HierarchicalDataTemplate 
     DataType="forest" 
     ItemsSource="{Binding XPath=tree}"> 
     <TextBox 
      Text="{Binding XPath=data}" /> 
    </HierarchicalDataTemplate> 
    <HierarchicalDataTemplate 
     DataType="tree" 
     ItemsSource="{Binding XPath=branch}"> 
     <TextBox 
      Text="{Binding XPath=data}" /> 
    </HierarchicalDataTemplate> 
    <HierarchicalDataTemplate 
     DataType="branch" 
     ItemsSource="{Binding XPath=leaf}"> 
     <TextBox 
      Text="{Binding XPath=data}" /> 
    </HierarchicalDataTemplate> 
    <DataTemplate 
     DataType="leaf"> 
     <TextBox 
      Text="{Binding XPath=data}" /> 
    </DataTemplate> 

    <XmlDataProvider 
     x:Key="dataxml" 
     XPath="forestPad" Source="D:\fp.xml"> 
    </XmlDataProvider> 
</Window.Resources> 

可以代替設置XmlDataProvider編程的Source

dp = this.FindResource("dataxml") as XmlDataProvider; 
dp.Source = new Uri(@"D:\fp.xml"); 

此外,重新保存編輯的,因爲這很容易:

dp.Document.Save(dp.Source.LocalPath); 

TreeView本身需要一個Name和保稅到ItemsSourceXmlDataProvider

<TreeView 
    Name="treeview" 
    ItemsSource="{Binding Source={StaticResource dataxml}, XPath=.}"> 

我這個例子,我做了TwoWay與每個節點上TextBox ES結合,但是當涉及到編輯只是一個節點在單獨的單獨的TextBox或其他控件中,您可以將它綁定到TreeView的當前選定項目。您還可以將上述TextBox es更改爲TextBlock s,因爲點擊TextBox實際上並未選擇相應的TreeViewItem

<TextBox 
    DataContext="{Binding ElementName=treeview, Path=SelectedItem}" 
    Text="{Binding XPath=data, UpdateSourceTrigger=PropertyChanged}"/> 

必須使用兩個Binding真正的原因是,你不能使用PathXPath在一起。

編輯:

李提摩太羅素問有關保存CDATA的數據元素。首先,有點在InnerXmlInnerText

在幕後,XmlDataProvider正在使用XmlDocument,它的樹是XmlNodes。當諸如「stuff」的字符串被分配給XmlNodeInnerXml屬性時,那些標籤就是真正的標籤。獲取或設置InnerXml時不會轉義,並且它被解析爲XML。

但是,如果將它分配給InnerText屬性,則尖括號將與實體& lt;和& gt ;.當值被回收時發生相反的情況。實體(如& lt;)被解析回字符(如<)。

因此,如果我們在數據元素存儲字符串包含XML,實體已經逃跑了,我們需要撤消只需添加一個CDATA段,該節點的孩子之前檢索InnerText ...

XmlDocument doc = dp.Document; 

XmlNodeList nodes = doc.SelectNodes("//data"); 

foreach (XmlNode node in nodes) { 
    string data = node.InnerText; 
    node.InnerText = ""; 
    XmlCDataSection cdata = doc.CreateCDataSection(data); 
    node.AppendChild(cdata); 
} 

doc.Save(dp.Source.LocalPath); 

如果節點已經有一個CDATA節並且該值沒有任何改變,那麼它仍然有一個CDATA節,我們基本上用相同的替代它。但是,通過我們的綁定,如果我們更改數據元素內容的值,它將替換CDATA以支持轉義字符串。然後我們必須解決它們。

+0

謝謝喬爾,這工作。一個問題,但。我用CDATA節將數據元素中的內容包圍起來,以便可以存儲Xml。有沒有辦法控制XmlDataProvider如何寫出數據元素? – 2008-10-09 22:09:52

2

我們有類似的問題。你可能會發現閱讀this article有幫助。我們使用了描述的ViewModel模式,它簡化了一切。