【问题标题】:How to bind Xml Attribute to Treeview nodes, while databinding XDocument to WPF Treeview如何将 Xml 属性绑定到 Treeview 节点,同时将 XDocument 数据绑定到 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也有类似的讨论。

任何指针都会很有帮助。

【问题讨论】:

    标签: c# wpf data-binding xaml treeview


    【解决方案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,它们会解耦,你不觉得吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 2011-02-09
    • 2017-07-09
    • 2010-10-24
    • 2011-07-06
    相关资源
    最近更新 更多