如何将 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的主要内容,如果未能解决你的问题,请参考以下文章

Xml 数据到 WPF TreeView 的双向绑定

WPF中的TreeView,如何改变子节点的顺序, 给个例子,多谢

treeview 节点的属性NavigateUrl如何带参跳转并跳转到指定页面?

WPF 之 TreeView节点重命名

xml文档绑定某个属性值到treeview算法

使用WPF在虚拟化TreeView中选择节点