2008-10-26 5 views
4

J'ai un XML qui doit être databound à WPF TreeView . Ici, le XML peut avoir une structure différente. TreeView doit être suffisamment générique pour pouvoir charger n'importe quelle permutation de la hiérarchie. Cependant, une XAttribute sur les nœuds (appelé Titre) devrait être DataBound au texte d'en-tête de TreeViewItem et pas le nodename.Comment lier l'attribut XML aux noeuds Treeview, pendant la liaison de données XDocument à WPF Treeview

XML à être lié:

<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 de XAML qui charge XML à XDocument et se lie à TREEVIEW

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

Ainsi, dans le balisage XAML nous lient le nom à l'en-tête de TreeViewItem.

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

Cependant, je veux lier à Titre attribut de la section, la boucle et la page dans le fichier XML ci-dessus. J'ai lu qu'il n'est pas possible d'utiliser XPath lors de la liaison de XDocument. Mais il doit y avoir un moyen de lier l'attribut Title au texte d'en-tête de TreeViewItem. J'ai essayé d'utiliser @Title,. [@ Titre] etc. Mais aucun ne semblait fonctionner. Cette discussion thread on MSDN Forums a une discussion similaire.

Tous les pointeurs seraient très utiles.

Répondre

10

Hourra !!! J'ai compris comment lier XAttribute. Ce n'est pas intuitif et ce n'est pas facilement imaginable. Mais voici comment cela peut être fait.

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

Il est difficile d'imaginer que Title peut être directement utilisé dans les accolades carrées.

More @ this MSDN link

+1

Je pense, il devrait Attributs au lieu de l'Attribut ... Au moins pour moi cela ne fonctionne pas ... – binco

+0

Que faire de Binding XPath = @ Title'? –

2

Je pense que tout ce que vous devez faire est de créer un HierarchicalDataTemplate pour chaque type de noeud dans votre XML, chargez votre xml dans un XmlDataProvider, puis lier qui à la TreeView. Le téléviseur fonctionne avec le XDP pour lier les données, et quelque part sur la ligne, ils déterminent les HDT que vous avez définis et font correspondre leur DataType aux noms des nœuds de votre XML. Vous pourriez avoir quelques problèmes avec vos XPATHs changeant avec les différents types de données, mais garder ces flexibles est une autre question. Par exemple, j'ai une petite application de test regex. Il inclut un système d'aide qui est essentiellement toutes les différentes parties de regex répertoriées dans un arbre: Catégories et parties avec des descriptions, des info-bulles et d'autres choses. Les données sur les pièces sont stockées en tant que source de données XML. Depuis sa statique, je viens de créer une ressource statique avec les ressources de l'application:

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

Ensuite, j'ai créé HierarchicalDataTemplates pour chaque type de noeud dans les données (encore une fois, tout cela est dans les ressources de l'application):

<!-- Category data template --> 
<HierarchicalDataTemplate 
    DataType="Category" 
    ItemsSource="{Binding XPath=*}"> 
    <TextBlock 
     Focusable="False" 
     Text="{Binding [email protected]}" 
     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 [email protected]}" /> 
     <TextBlock 
      Text=" - " /> 
     <TextBlock 
      Text="{Binding [email protected]}" /> 
    </WrapPanel> 
</HierarchicalDataTemplate> 

Enfin, je viens de l'arbre lié à la 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> 

Et qui est tout ce que vous avez à faire. TreeView et le XmlDataProvider prendront soin de trouver et d'utiliser le bon HDT's pour les bons nœuds dans les données. La partie la plus difficile de tout cela est de déterminer vos xpaths pour la liaison.Cela peut être un peu compliqué, comme si vos chemins étaient incorrects, vous n'obtiendrez rien dans l'arborescence et il n'y aura pas d'erreurs (il existe des moyens d'augmenter les rapports d'erreurs dans la liaison de données dans WPF, mais c'est une autre question) .

+0

Merci Will. Vous avez ajouté de très bonnes informations. Mais je n'aime pas XmlDataProvider dans le cas où je travaille avec. Bien que mon exemple charge le fichier XML à partir d'un fichier, en réalité, je reçois XDocument directement pour être lié à la télévision. J'ai trouvé la solution cependant. Va le poster comme réponse. – Vin

+0

Comme vous pouvez le voir dans mon exemple, l'utilisation d'un XmlDataProvider peut grandement simplifier votre xaml en vous permettant de sortir tous les modèles de votre arbre en HDT. Vous pouvez obtenir ce XDocument en un dans votre codebehind, pas de problème. Mais si cela fonctionne pour vous, plus de pouvoir à vous. – Will

+0

La chose ici, My XDocument devrait être une représentation d'objet de TreeView. Si j'utilise XmlDataProvider, ils sont découplés, n'est-ce pas? – Vin

Questions connexes