Как связать атрибут Xml с узлами Treeview, в то время как XDocument связывает данные с WPF Treeview - PullRequest
4 голосов
/ 26 октября 2008

У меня есть 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 для Section, Loop и Page в Xml выше. Я читал, что невозможно использовать XPath при связывании XDocument. Но должен быть способ связать атрибут Title с текстом заголовка TreeViewItem. Я пытался использовать @Title,. [@ Title] и т. Д. Но ни один из них не помог.

В этой теме на форумах MSDN есть аналогичное обсуждение.

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

Ответы [ 2 ]

10 голосов
/ 26 октября 2008

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

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

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

Подробнее @ эта ссылка MSDN

2 голосов
/ 26 октября 2008

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

...