双向XML数据的结合WPF的树视图 [英] Two-way binding of Xml data to the WPF TreeView
问题描述
我试图重写我的 ForestPad 利用WPF为presentation层应用程序。在的WinForms,我填充编程的每个节点,但我想利用WPF的的数据绑定功能的优势,如果可能的话。
在一般的,什么是双向数据绑定的WPF的TreeView的最佳方式对XML文档?
一个通用的解决方案是好的,但参考,我试图绑定到看起来像这样的XML文档的结构:
<?XML版本=1.0编码=UTF-8&GT?;
< forestPad
GUID =6c9325de-dfbe-4878-9d91-1a9f1a7696b0
创建=2004年5月14日上午01点05分10秒
更新=2004年5月14日上午01时07分41秒>
<森林
NAME =A林节点
GUID =b441a196-7468-47c8-a010-7ff83429a37b
创建=01/01/2003 1:00:00 AM。
更新=2004年5月14日上午01时06分15秒>
<数据>
<![CDATA [A林节点
这是林节点的文本]>
< /数据>
<树
NAME =树节点
GUID =768eae66-e9df-4999-b950-01fa9be1a5cf
创建=2004年5月14日上午01时05分38秒
更新=2004年5月14日上午01时06分11秒>
<数据>
<![CDATA [树节点
这是树节点的文本]>
< /数据>
<分支
NAME =分支节点
GUID =be4b0993-d4e4-4249-8aa5-fa9c940ae2be
创建=2004年5月14日上午01时06分00秒
更新=2004年5月14日上午01时06分24秒>
<数据>
<![CDATA [分支节点
这是分支节点的文本]方式>&下; /数据>
<叶
NAME =叶节点
GUID =9c76ff4e-3ae2-450e-b1d2-232b687214aa
创建=2004年5月14日上午01时06分26秒
更新=2004年5月14日上午01时06分38秒>
<数据>
<![CDATA [叶节点
这是叶节点的文本]>
< /数据>
< /叶>
< /支>
< /树>
< /森林>
< / forestPad>
那么,它会更容易,如果你的元素层次更像...
<节点类型=森林>
<节点类型=树>
...
...而不是当前的架构。
由于-是,你需要4 HierarchicalDataTemplate
S,一个是包括根各层次的元素,一个的DataTemplate
为叶
元素:
< Window.Resources>
< HierarchicalDataTemplate
数据类型=forestPad
的ItemsSource ={结合的XPath =森林}>
<的TextBlock
文本=一个forestpad/>
< / HierarchicalDataTemplate>
< HierarchicalDataTemplate
数据类型=森林
的ItemsSource ={结合的XPath =树}>
<文本框
文本={结合的XPath =数据}/>
< / HierarchicalDataTemplate>
< HierarchicalDataTemplate
数据类型=树
的ItemsSource ={结合的XPath =分支}>
<文本框
文本={结合的XPath =数据}/>
< / HierarchicalDataTemplate>
< HierarchicalDataTemplate
数据类型=分支
的ItemsSource ={结合的XPath =叶}>
<文本框
文本={结合的XPath =数据}/>
< / HierarchicalDataTemplate>
<的DataTemplate
数据类型=叶子>
<文本框
文本={结合的XPath =数据}/>
< / DataTemplate中> < XmlDataProvider
X:键=dataxml
XPath的=forestPad来源=D:\\ fp.xml>
< / XmlDataProvider>
< /Window.Resources>
您可以代替设置的来源
的 XmlDataProvider
编程方式:
DP = this.FindResource(dataxml)作为XmlDataProvider;
dp.Source =新的URI(@D:\\ fp.xml);
此外,重新保存编辑是那么容易,因为这样的:
dp.Document.Save(dp.Source.LocalPath);
的 TreeView控件
本身需要名称
和的ItemsSource
键合到 XmlDataProvider
:
< TreeView控件
NAME =树视图
的ItemsSource ={绑定源= {StaticResource的dataxml},XPath的=。}>
我这个例子,我做了双向
与文本框结合
的每个节点,但在上课时谈到编辑只是一次在一个单独的,单一的文本框节点
或其它控制,你会被它绑定到 TreeView控件的当前选择的项目
。您也将改变上述文本框
下载到的TextBlock
S,如单击文本框
不实际选择相应的树型视图
。
<文本框
的DataContext ={绑定的ElementName =树视图,路径=的SelectedItem}
文本={结合的XPath =数据,UpdateSourceTrigger =的PropertyChanged}/>
究其原因,你必须使用两个绑定
s的,你不能使用路径
和 XPath的
在一起。
编辑:
李提摩太罗素问有关保存CDATA的数据元素。首先,在一个小 InnerXml
和的InnerText
。
在幕后, XmlDataProvider
是使用的XmlDocument
,与它的树将XMLNode
。当一个字符串,如东西被分配到一个的XmlNode
,那么这些标记是真正标记的 InnerXml
属性。无法回避完成获取或设置当 InnerXml
,它解析为XML。
然而,如果不是分配给的InnerText
属性,尖括号将与实体&放逃脱; LT;和&安培;取代。当值retreived情况相反。实体(如&放大器; LT)被解析回字符(比如≤)。
因此,如果我们在数据元素存储字符串包含XML,实体已经逃跑,我们需要撤消,仅仅通过检索的InnerText
添加CDATA节之前作为节点的孩子......
XmlDocument的DOC = dp.Document;XmlNodeList中的节点= doc.SelectNodes(//数据);的foreach(在节点XmlNode的节点){
字符串数据= node.InnerText;
node.InnerText =;
XmlCDataSection CDATA = doc.CreateCDataSection(数据);
node.AppendChild(CDATA);
}doc.Save(dp.Source.LocalPath);
如果该节点已经有一个CDATA部分和价值没有以任何方式被改变,那么它仍然有一个CDATA部分,我们基本上是用相同的替换它。但是,通过我们的结合,如果我们改变数据元素含量的价值,它取代赞成转义字符串的CDATA。然后,我们必须解决这些问题。
I am attempting to rewrite my ForestPad application utilizing WPF for the presentation layer. In WinForms, I am populating each node programmatically but I would like to take advantage of the databinding capabilities of WPF, if possible.
In general, what is the best way to two-way databind the WPF TreeView to an Xml document?
A generic solution is fine but for reference, the structure of the Xml document that I am trying to bind to looks like this:
<?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>
Well, it would be easier if your element hierarchy was more like...
<node type="forest">
<node type="tree">
...
...rather than your current schema.
As-is, you'll need 4 HierarchicalDataTemplate
s, one for each hierarchical element including the root, and one DataTemplate
for leaf
elements:
<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>
You can instead set the Source
of the XmlDataProvider
programmatically:
dp = this.FindResource( "dataxml" ) as XmlDataProvider;
dp.Source = new Uri( @"D:\fp.xml" );
Also, re-saving your edits is as easy as this:
dp.Document.Save( dp.Source.LocalPath );
The TreeView
itself needs a Name
and an ItemsSource
bonded to the XmlDataProvider
:
<TreeView
Name="treeview"
ItemsSource="{Binding Source={StaticResource dataxml}, XPath=.}">
I this example, I did TwoWay
binding with TextBox
es on each node, but when it comes to editing just one node at a time in a separate, single TextBox
or other control, you would be binding it to the currently selected item of the TreeView
. You would also change the above TextBox
es to TextBlock
s, as clicking in the TextBox
does not actually select the corresponding TreeViewItem
.
<TextBox
DataContext="{Binding ElementName=treeview, Path=SelectedItem}"
Text="{Binding XPath=data, UpdateSourceTrigger=PropertyChanged}"/>
The reason you must use two Binding
s is that you cannot use Path
and XPath
together.
Edit:
Timothy Lee Russell asked about saving CDATA to the data elements. First, a little on InnerXml
and InnerText
.
Behind the scenes, XmlDataProvider
is using an XmlDocument
, with it's tree of XmlNodes
. When a string such as "stuff" is assigned to the InnerXml
property of an XmlNode
, then those tags are really tags. No escaping is done when getting or setting InnerXml
, and it is parsed as XML.
However, if it is instead assigned to the InnerText
property, the angle brackets will be escaped with entities < and >. The reverse happens when the value is retreived. Entities (like <) are resolved back into characters (like <).
Therefore, if the strings we store in the data elements contain XML, entities have been escaped, and we need to undo that simply by retrieving InnerText
before adding a CDATA section as the node's child...
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 );
If the node already has a CDATA section and the value has not been changed in any way, then it still has a CDATA section and we essentially replace it with the same. However, through our binding, if we change the value of the data elements contents, it replaces the CDATA in favor of an escaped string. Then we have to fix them.
这篇关于双向XML数据的结合WPF的树视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!