Xml AttributeをTreeviewノードにバインドし、XDocumentをWPF Treeviewにデータバインドする方法
-
04-07-2019 - |
質問
WPF TreeView にデータバインドする必要があるXMLがあります。ここで、XMLは異なる構造を持つことができます。 TreeViewは、階層の順列をロードするのに十分な汎用データバインドである必要があります。ただし、ノード上の XAttribute ( Title と呼ばれる)はTreeViewItemの header text にデータバインドされ、ノード名ではなく 。
バインドされる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のセクション、ループ、ページのタイトル属性にバインドします。 XDocumentのバインド中にXPathを使用することはできないと読みました。ただし、 Title 属性をTreeViewItemのヘッダーテキストにバインドする方法が必要です。 @Title、。[@ Title]などを使用してみました。しかし、どれも機能していないようです。
このスレッドMSDNフォーラムにも同様の議論があります。
任意のポインターが非常に役立ちます。
解決
ハラー!!! XAttributeをバインドする方法を見つけました。直感的ではなく、簡単に想像もできません。しかし、ここでそれを行う方法があります。
<TreeViewItem Header="{Binding Path=Attribute[Title].Value}"/>
Titleを角括弧で直接使用できるとは想像しにくいです。
他のヒント
必要なのは、 HierarchicalDataTemplateを作成することだけです XMLの各ノードタイプについて、XMLをにロードしますXmlDataProvider を選択し、 that をTreeViewにバインドします。 TVは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のデータバインディングでエラー報告を増やす方法はありますが、それは別の質問です) 。