问题描述
我正在尝试使用WPF为表示层重写我的应用程序。在WinForms中,我以编程方式填充每个节点,但如果可能,我想利用WPF的数据绑定功能。
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.
一般来说,最好的方法是双向数据绑定WPF TreeView到一个Xml文档?
In general, what is the best way to two-way databind the WPF TreeView to an Xml document?
通用的解决方案很好,但是为了引用,我试图绑定到外观的Xml文档的结构像这样:
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.
按原样,您将需要4个 HierarchicalDataTemplate
,每个层级元素包括根,一个 DataTemplate
for leaf
元素:
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>
您可以将 Source
xmlDataProvider
以编程方式:
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 );
TreeView
本身需要一个名称
和 ItemsSource
绑定到 XmlDataProvider
:
The TreeView
itself needs a Name
and an ItemsSource
bonded to the XmlDataProvider
:
<TreeView
Name="treeview"
ItemsSource="{Binding Source={StaticResource dataxml}, XPath=.}">
我这个例子,我做了 TwoWay
binding在每个节点上使用 TextBox
es,但是当一个单独的 TextBox 或其他控件,您将绑定到
TreeView
当前选定的项目。您也可以将 TextBox
es更改为 TextBlock
,点击 TextBox
实际上并没有选择相应的 TreeViewItem
。
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}"/>
你必须使用两个
绑定的原因绑定
是不能一起使用路径
和 XPath
。
The reason you must use two
Binding
s is that you cannot use Path
and XPath
together.
编辑:
Timothy Lee Russell询问将CDATA保存到数据元素。首先,在
InnerXml
和 InnerText
。
Timothy Lee Russell asked about saving CDATA to the data elements. First, a little on
InnerXml
and InnerText
.
使用
XmlDataProvider
正在使用 XmlDocument
,其树为 XmlNodes
。当一个诸如stuff的字符串被分配给 XmlNode
的 InnerXml
属性时,那些标签是真正的标签。获取或设置 InnerXml
时不进行转义,并将其解析为XML。
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.
但是,如果是而是分配给
InnerText
属性,尖括号将以实体& lt;和& gt;当撤销该值时,会发生相反的情况。实体(如& lt)被解析成字符(如<)。
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 <).
因此,如果我们存储在数据元素中的字符串包含XML,被转义,我们需要通过检索
InnerText
,然后再将CDATA部分添加到节点的子节点中。
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 );
如果节点已经有CDATA部分,并且值没有以任何方式更改,那么它仍然有一个CDATA部分,我们基本上替换它。然而,通过我们的绑定,如果我们更改数据元素的内容的值,它将替换CDATA,有利于转义的字符串。然后我们必须修复它们。
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 TreeView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!