Come associare l'attributo Xml ai nodi Treeview, mentre si associa XDocument a WPF Treeview
-
04-07-2019 - |
Domanda
Ho un XML che deve essere integrato in un TreeView WPF . Qui l'XML può avere una struttura diversa. TreeView dovrebbe essere abbastanza generico dal database per caricare qualsiasi permutazione della gerarchia. Tuttavia, un attributo X sui nodi (chiamato titolo ) deve essere basato su dati nel testo dell'intestazione e non nel nome nodo .
XML da associare:
<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>
Il codice di XAML dietro carica XML da XDocument e lo lega a TreeView
public partial class TreeViewer : Window
{
public TreeViewer()
{
InitializeComponent();
XDocument doc = XDocument.Parse(File.ReadAllText(@"C:\MyWizard.xml"));
_treeView.DataContext = doc;
}
}
Quindi nel markup XAML stiamo legando il nome all'intestazione TreeViewItem.
<TreeViewItem Header="{Binding Path=Name}"/>
Tuttavia, voglio associarlo all'attributo Titolo di Sezione, Ciclo e Pagina nell'Xml sopra. Ho letto che non è possibile utilizzare XPath durante l'associazione di XDocument. Ma deve esserci un modo per associare l'attributo Titolo al testo dell'intestazione di TreeViewItem. Ho provato a usare @Title,. [@ Title] ecc. Ma nessuno sembrava funzionare.
Questo su Forum MSDN ha una discussione simile.
Qualsiasi puntatore sarebbe di grande aiuto.
Soluzione
Evviva !!! Ho capito come legare XAttribute. Non è intuitivo e non è facilmente immaginabile. Ma ecco come si può fare.
<TreeViewItem Header="{Binding Path=Attribute[Title].Value}"/>
È difficile immaginare che il titolo possa essere utilizzato direttamente tra parentesi quadre.
Altri suggerimenti
Penso che tutto ciò che devi fare è creare un HierarchicalDataTemplate per ogni tipo di nodo nel tuo XML, carica il tuo xml in un XmlDataProvider , quindi associa quello a TreeView. La TV lavora con l'XDP per associare i dati e da qualche parte lungo la linea capiscono quali HDT hai definito e abbinano il loro DataType ai nomi dei nodi nel tuo XML. Potresti avere alcuni problemi con i tuoi XPATH che cambiano con i diversi tipi di dati, ma mantenerli flessibili è un'altra domanda.
Ad esempio, ho una piccola app di test regex. Include un sistema di aiuto che è essenzialmente tutte le diverse parti regex elencate in un albero: categorie e parti con descrizioni, descrizioni comandi e altre cose. I dati sulle parti vengono archiviati come origine dati XML. Da quando è statico, ho appena creato una risorsa statica con le risorse dell'applicazione:
<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>
Successivamente, ho creato HierarchicalDataTemplates per ciascuno digitare il nodo nei dati (di nuovo, tutto questo è nelle risorse dell'applicazione):
<!-- 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>
Infine, ho appena associato l'albero a 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>
Ed è tutto ciò che devi fare. TreeView e XmlDataProvider si occuperanno di trovare e utilizzare il corretto HDT's per i nodi corretti nei dati. La parte più difficile di tutto questo è capire i tuoi xpath per il binding. Può diventare un po 'complicato, come se i tuoi percorsi non fossero corretti, finirai per non ottenere nulla nella struttura e non ci saranno errori (ci sono modi per aumentare la segnalazione degli errori nel database nel WPF, ma questa è un'altra domanda) .