Как привязать атрибут Xml к узлам Treeview при привязке XDocument к WPF Treeview

У меня есть XML, который необходимо привязать к WPF TreeView. Здесь 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>

Программный код XAML, который загружает XML в XDocument и связывает его с TreeView.

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}"/>

Однако я хочу привязать его к атрибуту Title раздела, цикла и страницы в XML выше. Я читал, что использовать XPath при привязке XDocument невозможно. Но должен быть способ привязать атрибут Title к тексту заголовка TreeViewItem. Я пробовал использовать @Title,. [@ Title] и т. Д. Но, похоже, ничего не помогло.

Эта ветка на форумах MSDN имеет аналогичное обсуждение.

Любые указатели были бы очень полезны.


person Vin    schedule 26.10.2008    source источник


Ответы (2)


Ура !!! Я понял, как привязать XAttribute. Это не интуитивно понятно и трудно вообразить. Но вот как это можно сделать.

<TreeViewItem Header="{Binding Path=Attribute[Title].Value}"/>

Трудно представить, что Title можно напрямую использовать в квадратных скобках.

Еще по этой ссылке MSDN

person Vin    schedule 26.10.2008
comment
Я думаю, это должны быть Attributes вместо Attribute ... По крайней мере, для меня это не работает ... - person binco; 08.06.2010
comment
Что насчет того, чтобы делать Binding XPath=@Title? - person Sarah Vessels; 04.08.2010

Я думаю, все, что вам нужно сделать, это создать HierarchicalDataTemplate для каждого типа узла в вашем XML загрузите свой xml в XmlDataProvider, а затем привяжите это к 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 для правильных узлов в данных. Самая сложная часть всего этого - выяснить ваши xpaths для привязки. Это может быть немного сложно, так как если ваши пути неверны, вы в конечном итоге ничего не получите в дереве и не будет никаких ошибок (есть способы увеличить количество сообщений об ошибках в привязке данных в WPF, но это другой вопрос) .

person Community    schedule 26.10.2008
comment
Спасибо, Уилл. Вы добавили действительно полезную информацию. Но мне не нравится XmlDataProvider в том случае, с которым я работаю. Хотя мой образец загружает XML из файла, на самом деле я получаю XDocument напрямую для привязки к TV. Но я нашел решение. Отправлю как ответ. - person Vin; 26.10.2008
comment
Как вы можете видеть из моего примера, использование XmlDataProvider может значительно упростить ваш xaml, позволив вам разбить все шаблоны для вашего дерева на HDT. Вы можете поместить этот XDocument в один в своем коде, без проблем. Но если это сработает для вас, больше власти для вас. - person ; 26.10.2008
comment
Дело в том, что My XDocument должен быть объектным представлением TreeView. Если я использую XmlDataProvider, они развязаны, вам не кажется? - person Vin; 29.10.2008