2010-09-20 8 views
1

Je travaille sur une application qui utilise une ListBox richement formatée. Une des choses dont j'ai besoin est de lier plusieurs informations à un bouton qui se trouve dans le DataTemplate de ListBox.WPF - DataTemplate - Utilisation de la liaison d'éléments dans une propriété jointe

Ceci est une simplification excessive de mon code réel que j'ai fait pour vous aider à comprendre le problème.

est ici un morceau de XAML à l'intérieur du DataTemplate qui fonctionne:

<Button Command="local:MediaCommands.StreamVideo" 
    CommandParameter="{Binding Path=Folder}" /> 

Lorsque j'appuie sur le bouton, il envoie la propriété Folder de l'élément de données que cette liste est basée sur (le membre de ItemsSource que l'élément de liste actuel est affiché). Cependant, j'ai besoin d'un autre élément de données, la propriété Filename de l'élément actuel. Pour ce faire, j'ai mis en place une nouvelle classe, FileInfo, qui contient les propriétés de dépendance pour Folder et Filename. Je puis remplacé le code XAML avant avec:

<Button Command="local:MediaCommands.StreamVideo"> 
    <Button.CommandParameter> 
     <data:FileInfo Folder="{Binding Path=Folder}" 
      Filename="{Binding Path=Filename}" /> 
    </Button.CommandParameter> 
</Button> 

Cependant, la seule chose que mon code me envoie est un objet FileInfo vide. Notez que si je modifie le code XAML ci-dessus pour inclure des valeurs littérales pour Folder et Filename, le code fonctionne correctement, en ce sens qu'il crée correctement l'objet FileInfo et attribue les propriétés correctes.

Pour référence, ma classe FileInfo ressemble un peu à ceci:

class FileInfo : DependencyObject { 
    public static readonly DependencyProperty FolderProperty; 
    public static readonly DependencyProperty FilenameProperty; 
    static FileInfo() { 
     FolderProperty = DependencyProperty.Register("Folder", 
      typeof(string), typeof(FileInfo)); 
     FilenameProperty = DependencyProperty.Register("Filename", 
      typeof(string), typeof(FileInfo)); 
    } 
    public string Folder { 
     get { return (string) GetValue(FolderProperty); } 
     set { SetValue(FolderProperty, value); } 
    } 
    public string Filename { 
     get { return (string) GetValue(FilenameProperty); } 
     set { SetValue(FilenameProperty, value); } 
    } 
} 

Ignorant le fait que, dans ce cas, je ne pouvais tout simplement passer une référence à l'objet de données lui-même (dans ma demande réelle, je besoin de tirer des données d'un couple imbriqué ListBox, mais le problème est le même), quelqu'un peut-il voir ce qui se passe ici? Mes propriétés de dépendance n'ont-elles pas été déclarées correctement? Ai-je besoin de faire quelque chose d'original avec les fixations?

+0

Très curieux. Une chose qui m'aide à comprendre les problèmes de liaison est d'activer l'option lancée sous Debug -> Exceptions -> Assistants de débogage gérés -> BindingFailure. Peut-être que le débogueur vous dira quelque chose d'utile si vous faites cela. – Jacob

+0

J'ai activé cette fonctionnalité mais elle n'a rien signalé de plus. Ça doit être autre chose. – Ethan

Répondre

3

Les liaisons qui ne déclarent pas explicitement une source s'appuient sur le DataContext comme source. Vous n'avez pas déclaré DataContext sur l'occurrence FileInfo, ce qui signifie normalement qu'un DataContext hérité serait utilisé. L'héritage DataContext dépend à la fois de FrameworkElement et de l'arborescence Visual d'exécution, qui ne sont pas utilisés lorsque vous utilisez une classe dérivée non-FrameworkElement affectée à une propriété qui ne s'affiche pas dans l'arborescence.

+0

J'ai essayé de faire en sorte que 'FileInfo' hérite de' FrameworkElement' au lieu de 'DependencyObject', mais cela n'a pas résolu le problème. Ai-je mal interprété votre solution? – Ethan

+2

John a également mentionné que l'objet doit faire partie de l'arborescence Visual afin de faire fonctionner l'héritage DataContext. Dans votre cas, FileInfo ne l'est pas. Donc, il ne prend pas le DataContext. Quoi qu'il en soit, une solution possible pour ce que vous avez ci-dessus est d'avoir un IValueConverter qui retourne une instance FileInfo donnée à votre classe de données. Ce faisant, votre CommandParameter sera alors déclaré comme

+0

Le problème que je vois avec cela (et ce peut être un non-problème) est que mes données ne viennent pas seulement de ma classe de données. Au contraire, j'ai besoin d'un champ de ma classe de données et de deux champs d'autres éléments ('ListBox's) dans le modèle de données.Strictement parlant, je pourrais simplement retourner aucun paramètre et programmer le rappel du bouton afin qu'il traverse l'arbre des éléments, mais cela prendrait beaucoup de travail et serait horriblement inélégant. Je pense qu'il devrait y avoir une meilleure solution. – Ethan