我有一个XML需要数据绑定到 WPF TreeView 。这里的XML可以有不同的结构。 TreeView应该是数据绑定通用的,足以加载任何层次结构的排列。但是,节点上的 XAttribute (称为标题)应该数据绑定到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}"/>
但是,我想将它绑定到上面Xml中Section,Loop和Page的 Title 属性。我读到在绑定XDocument时不可能使用XPath。但是必须有一种方法将 Title 属性绑定到TreeViewItem的Header文本。我尝试使用@Title,。[@ Title]等。但似乎都没有用。
此thread on MSDN Forums也有类似的讨论。
任何指针都会非常有用。
答案 0 :(得分:10)
华友世界!我想出了如何绑定XAttribute。它不直观,也不容易想象。但这是如何做到的。
<TreeViewItem Header="{Binding Path=Attribute[Title].Value}"/>
很难想象Title可以直接用在方括号中。
答案 1 :(得分:2)
我认为您需要做的就是为XML中的每个节点类型创建一个HierarchicalDataTemplate,将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's。所有这一切中最困难的部分是找出绑定的xpath。它可能会有点棘手,好像你的路径不正确,你最终会在树中得不到任何错误(有很多方法可以增加WPF数据绑定中的错误报告,但这是另一个问题) 。