Как привязать Xml-атрибут к узлам Treeview при привязке данных XDocument к WPF Treeview
-
04-07-2019 - |
Вопрос
У меня есть XML, который должен быть привязан к базе данных Просмотр дерева WPF.Здесь XML может иметь разную структуру.TreeView должен быть достаточно общим для привязки к данным, чтобы загружать любую перестановку иерархии.Однако an Атрибут XAttribute ( XAttribute ) на узлах (называемых Название) должен быть привязан к базе данных treeviewitem's текст заголовка и не имя узла.
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>
codebehind 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}"/>
Тем не менее, я хочу привязать его к Название атрибут раздела, Цикла и Страницы в приведенном выше XML.Я читал, что невозможно использовать XPath при привязке XDocument .Но должен быть способ связать Название атрибут к тексту заголовка TreeViewItem.Я пробовал использовать @Title, .[@Title] и т.д.Но, похоже, ничего из этого не сработало.
Это тема на форумах MSDN ведет аналогичную дискуссию.
Любые указания были бы очень полезны.
Решение
Ура !!!Я выяснил, как привязать XAttribute.Это не интуитивно понятно, и это нелегко вообразить.Но вот как это можно сделать.
<TreeViewItem Header="{Binding Path=Attribute[Title].Value}"/>
Трудно представить, что заголовок может быть непосредственно использован в квадратных скобках.
Другие советы
Я думаю, все, что вам нужно сделать, это создать Иерархическая табличка данных для каждого типа узла в вашем XML-файле загрузите ваш xml-файл в XmlDataProvider - поставщик XML - данных, а затем свяжите это к просмотру дерева.Телевизор работает с XDP для привязки данных, и где-то по ходу дела они выясняют, какие HDT вы определили, и сопоставляют их тип данных с именами узлов в вашем XML.Возможно, у вас возникли некоторые проблемы с изменением ваших XPaths в зависимости от различных типов данных, но сохранение их гибкости - это другой вопрос.
Например, у меня есть небольшое тестовое приложение для регулярных выражений.Он включает в себя справочную систему, которая по сути представляет собой все различные части регулярных выражений, перечисленные в дереве:Категории и детали с описаниями, всплывающими подсказками и прочим.Данные о деталях хранятся в виде источника 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>
Затем я создал Иерархические таблички с данными для каждого типа узла в данных (опять же, все это находится в ресурсах приложения):
<!-- 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>
И это все, что вам нужно сделать.Древовидный вид и XmlDataProvider - поставщик XML - данных позаботится о поиске и использовании правильного HDT-х для правильных узлов в данных.Самая сложная часть всего этого - определить ваши xpaths для привязки.Это может стать немного сложнее, поскольку, если ваши пути неверны, вы в конечном итоге ничего не получите в дереве и не будет никаких ошибок (есть способы увеличить количество отчетов об ошибках при привязке данных в WPF, но это другой вопрос).