如何将 Xml 属性绑定到 Treeview 节点,同时将 XDocument 数据绑定到 WPF Treeview
Posted
技术标签:
【中文标题】如何将 Xml 属性绑定到 Treeview 节点,同时将 XDocument 数据绑定到 WPF Treeview【英文标题】:How to bind Xml Attribute to Treeview nodes, while databinding XDocument to WPF Treeview 【发布时间】:2010-09-19 06:53:27 【问题描述】:我有一个需要数据绑定到 WPF TreeView 的 XML。这里的 XML 可以有不同的结构。 TreeView 应该是足够通用的数据绑定来加载层次结构的任何排列。然而,节点上的 XAttribute(称为 Title)应该数据绑定到 TreeViewItem 的 标题文本 而不是节点名 .
要绑定的XML:
<Wizard>
<Section Title="Home">
<Loop Title="Income Loop">
<Page Title="Employer Income"/>
<Page Title="Parttime Job Income"/>
<Page Title="Self employment Income"/>
</Loop>
</Section>
<Section Title="Deductions">
<Loop Title="Deductions Loop">
<Page Title="Travel spending"/>
<Page Title="Charity spending"/>
<Page Title="Dependents"/>
</Loop>
</Section>
</Wizard>
XAML:
<Window x:Class="Wpf.DataBinding.TreeViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Wpf.DataBinding"
Title="TreeViewer" Height="300" Width="300">
<Window.Resources>
<HierarchicalDataTemplate ItemsSource="Binding Path=Elements" x:Key="TVTemplate">
<TreeViewItem Header="Binding Path=Name"/>
</HierarchicalDataTemplate>
</Window.Resources>
<StackPanel>
<TreeView x:Name="_treeView" Style="StaticResource TVallExpanded"
ItemsSource="Binding Path=Root.Elements"
ItemTemplate="StaticResource TVTemplate" />
</StackPanel>
</Window>
将 XML 加载到 XDocument 并将其绑定到 TreeView 的 XAML 代码隐藏
public partial class TreeViewer : Window
public TreeViewer()
InitializeComponent();
XDocument doc = XDocument.Parse(File.ReadAllText(@"C:\MyWizard.xml"));
_treeView.DataContext = doc;
所以在 XAML 标记中,我们将 Name 绑定到 TreeViewItem 的标头。
<TreeViewItem Header="Binding Path=Name"/>
但是,我想将它绑定到上面Xml 中Section、Loop 和Page 的Title 属性。我读到在绑定 XDocument 时无法使用 XPath。但是必须有一种方法可以将 Title 属性绑定到 TreeViewItem 的 Header 文本。我尝试使用@Title、.[@Title] 等。但似乎都没有。
这个thread on MSDN Forums也有类似的讨论。
任何指针都会很有帮助。
【问题讨论】:
【参考方案1】:万岁!!!我想出了如何绑定 XAttribute。它不直观,也不容易想象。但这里是如何做到的。
<TreeViewItem Header="Binding Path=Attribute[Title].Value"/>
很难想象Title可以直接用在方括号里。
More @ this MSDN link
【讨论】:
我认为,它应该是属性而不是属性......至少对我来说它不起作用......Binding XPath=@Title
怎么样?【参考方案2】:
我认为您需要做的就是为您的 XML 中的每个节点类型创建一个HierarchicalDataTemplate,将您的 xml 加载到一个XmlDataProvider,然后将 that 绑定到 TreeView。电视与 XDP 一起工作以绑定数据,并且在某处它们会找出您定义的 HDT 并将它们的 DataType 与 XML 中节点的名称相匹配。您的 XPATH 会随着不同类型的数据而变化,您可能会遇到一些问题,但保持这些灵活性是另一个问题。
例如,我有一个小的正则表达式测试应用程序。它包括一个帮助系统,它基本上是树中列出的所有不同的正则表达式部分:类别和带有描述、工具提示和其他内容的部分。有关零件的数据存储为 xml 数据源。由于它是静态的,我只是用应用程序的资源创建了一个静态资源:
<XmlDataProvider
x:Key="rxPartData"
XPath="RegexParts">
<x:XData>
<RegexParts
xmlns="">
<Category
Name="Character class"
ToolTip="Sets of characters used in matching">
<RegexPart
Regex="[%]"
Hint="Positive character group"
ToolTip="Matches any character in the specified group (replace % with one or more characters)" />
<!-- yadda -->
</Category>
</RegexParts>
</x:XData>
</XmlDataProvider>
接下来,我为数据中的每个节点类型创建了HierarchicalDataTemplates(同样,所有这些都在应用程序的资源中):
<!-- Category data template -->
<HierarchicalDataTemplate
DataType="Category"
ItemsSource="Binding XPath=*">
<TextBlock
Focusable="False"
Text="Binding XPath=@Name"
ToolTip="StaticResource CategoryTooltip"
ToolTipService.InitialShowDelay="0"
ToolTipService.ShowDuration="x:Static sys:Int32.MaxValue"
ToolTipService.HasDropShadow="True" />
</HierarchicalDataTemplate>
<!-- RegexPart data template -->
<HierarchicalDataTemplate
DataType="RegexPart"
ItemsSource="Binding XPath=*">
<WrapPanel
Focusable="False"
ToolTip="StaticResource RegexPartTooltip"
ToolTipService.InitialShowDelay="0"
ToolTipService.ShowDuration="x:Static sys:Int32.MaxValue"
ToolTipService.HasDropShadow="True">
<TextBlock
Text="Binding XPath=@Regex" />
<TextBlock
Text=" - " />
<TextBlock
Text="Binding XPath=@Hint" />
</WrapPanel>
</HierarchicalDataTemplate>
最后,我只是将树绑定到 XmlDataProvider:
<TreeView
Name="_regexParts"
DockPanel.Dock="Top"
SelectedItemChanged="RegexParts_SelectedItemChanged"
ItemsSource="Binding Source=StaticResource rxPartData, XPath=/RegexParts/Category"
ToolTip="Click the + to expand a category; click a part to insert it">
</TreeView>
这就是你所要做的。 TreeView 和XmlDataProvider 将负责为数据中的正确节点查找和使用正确的HDT's。所有这一切中最困难的部分是找出用于绑定的 xpath。它可能会有点棘手,好像你的路径不正确,你最终会在树中什么都没有,也不会出现任何错误(有一些方法可以增加 WPF 中数据绑定中的错误报告,但这是另一个问题) .
【讨论】:
谢谢威尔。您添加了一些非常好的信息。但在我正在使用的情况下,我不喜欢 XmlDataProvider。尽管我的示例从文件加载 XML,但实际上我将 XDocument 直接绑定到 TV。我找到了解决方案。将其发布为答案。 从我的示例中可以看出,使用 XmlDataProvider 可以通过允许您将树的所有模板分解为 HDT 来大大简化您的 xaml。您可以在代码隐藏中将该 XDocument 合并为一个,没问题。但是,如果这对您有用,那么您将获得更多力量。 这里的事情是,我的 XDocument 应该是 TreeView 的对象表示。如果我使用 XmlDataProvider,它们会解耦,你不觉得吗?以上是关于如何将 Xml 属性绑定到 Treeview 节点,同时将 XDocument 数据绑定到 WPF Treeview的主要内容,如果未能解决你的问题,请参考以下文章
WPF中的TreeView,如何改变子节点的顺序, 给个例子,多谢