4 Stimmen

Wie Xml-Attribut an Treeview-Knoten zu binden, während Datenbindung XDocument zu WPF Treeview

Ich habe eine XML, die databound zu einem sein muss WPF-Baumansicht . Hier kann das XML eine andere Struktur haben. Der TreeView sollte datengebunden und generisch genug sein, um jede Permutation der Hierarchie zu laden. Allerdings muss ein XAttribut auf den Knotenpunkten (genannt Titel ) sollte databound zu dem TreeViewItem's Kopftext y nicht der Node-Name .

XML, das gebunden werden soll:

<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's codebehind, das XML in XDocument lädt und es an TreeView bindet

public partial class TreeViewer : Window
{
    public TreeViewer()
    {
        InitializeComponent();
        XDocument doc = XDocument.Parse(File.ReadAllText(@"C:\MyWizard.xml"));
        _treeView.DataContext = doc;
    }
}

Im XAML Markup binden wir also Name an die Überschrift von TreeViewItem.

<TreeViewItem Header="{Binding Path=Name}"/>

Ich möchte es jedoch mit Titel Attribut von Abschnitt, Schleife und Seite in der obigen Xml-Datei. Ich habe gelesen, dass es nicht möglich ist, XPath beim Binden von XDocument zu verwenden. Aber es muss doch eine Möglichkeit geben, die Titel Attribut zum TreeViewItem's Header Text. Ich habe versucht, mit @Title, .[@Title] etc. Aber keine schien zu funktionieren.

Diese Thema in den MSDN-Foren hat eine ähnliche Diskussion.

Jeder Hinweis wäre sehr hilfreich.

13voto

Vin Punkte 6035

Hurra!!! Ich habe herausgefunden, wie man XAttribute bindet. Es ist nicht intuitiv und es ist nicht leicht vorstellbar. Aber hier ist, wie es gemacht werden kann.

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

Es ist schwer vorstellbar, dass der Titel direkt in eckigen Klammern verwendet werden kann.

Mehr unter diesem MSDN-Link

1 Stimmen

Ich denke, es sollte Attribute anstelle von Attribut... Zumindest bei mir klappt es nicht...

0 Stimmen

Wie wäre es mit Binding XPath=@Title ?

2voto

Ich denke, alles, was Sie tun müssen, ist eine HierarchicalDataTemplate für jeden Knotentyp in Ihrem XML, laden Sie Ihr XML in eine XmlDataProvider und binden dann dass zum TreeView. Das TV arbeitet mit der XDP, um Daten zu binden, und irgendwo auf der Linie finden sie heraus, welche HDTs Sie definiert haben und passen ihre DataType auf die Namen der Knoten in Ihrem XML. Sie könnten einige Probleme mit Ihren XPATHs haben, die sich mit den verschiedenen Datentypen ändern, aber diese flexibel zu halten ist eine andere Frage.

Ich habe zum Beispiel eine kleine Regex-Test-App. Es enthält ein Hilfesystem, das im Wesentlichen alle verschiedenen Regex-Teile in einem Baum aufgelistet ist: Kategorien und Teile mit Beschreibungen, Tooltips und anderen Dingen. Die Daten über die Teile sind als Xml-Datenquelle gespeichert. Da es statisch ist, habe ich einfach eine statische Ressource mit den Ressourcen der Anwendung erstellt:

<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>

Als nächstes habe ich HierarchicalDataTemplates für jeden Knotentyp in den Daten (auch hier befinden sich alle Informationen in den Ressourcen der Anwendung):

<!-- 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>

Zum Schluss habe ich den Baum an den XmlDataProvider gebunden:

<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>

Und das ist alles, was Sie tun müssen. Die TreeView und die XmlDataProvider kümmert sich um die Suche und Verwendung der richtigen HDTs für die richtigen Knoten in den Daten. Der schwierigste Teil von all dem ist das Herausfinden Ihrer xpaths für die Bindung. Es kann ein wenig knifflig, wie wenn Ihre Pfade falsch sind, werden Sie am Ende immer nichts in den Baum und es wird keine Fehler (es gibt Möglichkeiten zur Erhöhung der Fehlerberichterstattung in Datenbindung in WPF, aber das ist eine andere Frage).

0 Stimmen

Danke Will. Sie haben einige wirklich gute Informationen hinzugefügt. Aber ich mag nicht XmlDataProvider in dem Fall, mit dem ich arbeite. Obwohl mein Beispiel lädt die XML aus einer Datei, in Wirklichkeit bekomme ich XDocument direkt an TV gebunden werden. Ich habe jedoch die Lösung gefunden. Ich werde sie als Antwort posten.

0 Stimmen

Wie Sie an meinem Beispiel sehen können, kann die Verwendung eines XmlDataProviders Ihre Xaml stark vereinfachen, da Sie alle Vorlagen für Ihren Baum in HDTs aufteilen können. Sie können das XDocument in Ihrem Codebehind problemlos in eine Vorlage umwandeln. Aber wenn dies funktioniert für Sie, mehr Macht zu ya.

0 Stimmen

Die Sache hier ist, Mein XDocument sollte eine Objektdarstellung des TreeViews sein. Wenn ich XmlDataProvider verwenden sie entkoppelt werden, denken Sie nicht?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X