Comment puis-je utiliser WPF liaisons avec RelativeSource?
Comment puis-je utiliser RelativeSource
avec WPF liaisons et quels sont les différents cas d'utilisation?
Vous devez vous connecter pour publier un commentaire.
Comment puis-je utiliser RelativeSource
avec WPF liaisons et quels sont les différents cas d'utilisation?
Vous devez vous connecter pour publier un commentaire.
Si vous souhaitez lier à une autre propriété sur l'objet:
Si vous souhaitez obtenir une propriété d'un ancêtre:
Si vous souhaitez obtenir une propriété sur la basé sur un modèle parent (de sorte que vous pouvez le faire de manière 2 liaisons dans un ControlTemplate)
ou, plus courte (cela ne fonctionne que pour OneWay liaisons):
AncestorType
.FindAncestor
, avant deAncestorType
, j'obtiens l'erreur suivante: "RelativeSource n'est pas dans FindAncestor mode". (En VS2013, version Communautaire){Binding Path=DataContext.SomeProperty, RelativeSource=...
. C'était un peu inattendu pour moi comme un débutant quand j'essayais de le lier à un parent du DataContext dans un DataTemplate.La valeur par défaut de l'attribut de
RelativeSource
est leMode
de la propriété. Un ensemble complet de valeurs valides est donnée ici (à partir de MSDN):PreviousData Permet de vous lier au précédent élément de données (non pas que le contrôle qui contient l'élément de données) dans la liste des éléments de données en cours d'affichage.
TemplatedParent fait référence à l'élément pour lequel le modèle (dans lequel la liaison de données de l'élément existe) est appliquée. Ceci est similaire à la définition des TemplateBindingExtension et n'est applicable que si la Liaison est à l'intérieur d'un modèle.
Auto fait référence à l'élément sur lequel vous définissez la liaison et vous permet de lier une propriété de l'élément à l'autre de la propriété sur le même élément.
FindAncestor fait référence à l'ancêtre de la mère de la chaîne de la liaison de données de l'élément. Vous pouvez l'utiliser pour se lier à un ancêtre d'un type spécifique ou de ses sous-classes. C'est le mode que vous utilisez, si vous souhaitez spécifier AncestorType et/ou AncestorLevel.
Voici un visuel plus d'explication dans le contexte d'une architecture MVVM:
{Binding Message}
(un peu plus simple...)Path=DataContext.Message
pour obtenir les contraignant à travailler. Ce qui est logique, étant donné que vous pouvez le faire par rapport liaisons à la largeur/hauteur/etc. d'un contrôle.{Binding DataContext.DataContextProperty, ElementName=...}
les travaux, tandis que{Binding DataContextProperty}
pas. (Je suis familier avec l'utilisation de la MVVM modèle et le concept de la parenté ou de contexte de données de liaison.) La fenêtre n'a pas de propriété, en effet, avais-je suppose donc?Imaginez ce cas, un rectangle que nous voulons que sa hauteur est toujours égale à sa largeur, un carré disons. Nous pouvons faire cela en utilisant le nom de l'élément
Mais dans ce cas ci-dessus, nous sommes dans l'obligation d'indiquer le nom de l'objet de liaison, à savoir le rectangle. On peut atteindre le même but différemment à l'aide de la RelativeSource
Pour ce cas, nous ne sommes pas obligés de mentionner le nom de l'objet de liaison et la Largeur sera toujours égale à la Hauteur à chaque fois que la modification de la hauteur.
Si vous voulez paramètre de la Largeur à la moitié de la hauteur, alors vous pouvez le faire en ajoutant un convertisseur pour la Liaison d'extension de balisage.
Imaginons un autre cas maintenant:
Le cas ci-dessus est utilisé pour attacher une propriété donnée d'un élément donné à l'un de ses parent direct que cet élément contient une propriété qui est appelé Parent. Ce qui nous amène à une autre source par rapport au mode qui est le FindAncestor un.
Bechir Bejaoui expose le cas d'utilisation de la RelativeSources en WPF dans son article ici:
Dans WPF
RelativeSource
liaison expose troisproperties
définir:1. Mode: C'est un
enum
qui pourrait avoir quatre valeurs:2. AncestorType: lorsque le mode est
FindAncestor
puis de définir quel type d'ancêtre3. AncestorLevel: lorsque le mode est
FindAncestor
alors quel est le niveau de l'ancêtre (si il y a deux même type de parent dansvisual tree
)Voici un lien de référence.
N'oubliez pas TemplatedParent:
ou
Il est digne de remarque que, pour ceux qui tombent sur cette pensée de Silverlight:
Silverlight offre un sous-ensemble réduit seulement, de ces commandes
J'ai créé une bibliothèque pour simplifier la syntaxe de liaison de WPF, y compris le rendant plus facile à utiliser RelativeSource. Voici quelques exemples. Avant:
Après:
Voici un exemple de la façon dont la méthode de liaison est simplifiée. Avant:
Après:
Vous pouvez trouver à la bibliothèque ici: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html
Note dans le "AVANT" de l'exemple que j'utilise pour la méthode de liaison que le code a déjà été optimisé à l'aide de
RelayCommand
la dernière fois que j'ai vérifié n'est pas une partie native de WPF. Sans que le "AVANT" exemple aurait été encore plus.Utile de pièces et de morceaux:
Voici comment faire pour la plupart dans le code:
J'ai largement copié d' Liaison par rapport à la Source dans le code Derrière.
Aussi, la page MSDN, c'est très bon aussi loin que exemples: RelativeSource Classe
J'ai posté juste une autre solution pour accéder au DataContext d'un parent de l'élément en Silverlight qui fonctionne pour moi. Il utilise
Binding ElementName
.Je n'ai pas lu toutes les réponses, mais je veux juste ajouter cette information dans le cas de la source par rapport liaison de commande d'un bouton.
Lorsque vous utilisez une source par rapport à
Mode=FindAncestor
, la liaison doit être comme:Si vous n'ajoutez pas le DataContext dans votre chemin d'accès, au moment de l'exécution, il ne peut pas récupérer la propriété.
Ceci est un exemple de l'utilisation de ce modèle qui a fonctionné pour moi sur vide datagrid.
Si un élément ne fait pas partie de l'arbre visuel, puis RelativeSource ne fonctionnera jamais.
Dans ce cas, vous avez besoin d'essayer une autre technique, développée par Thomas Levesque.
Il a la solution sur son blog sous [WPF] Comment lier des données lorsque le DataContext est pas héréditaire. Et il fonctionne absolument avec brio!
Dans le cas peu probable que son blog est en panne, l'Annexe A contient une copie miroir de son article.
Merci de ne pas commenter ici, veuillez commentaire directement sur son blog.
Annexe A: Miroir de blog
Le DataContext de la propriété dans WPF est très pratique, car il est automatiquement héritée par tous les enfants de l'élément sur lequel vous l'attribuer; vous n'avez donc pas besoin de le mettre de nouveau sur chaque élément que vous voulez lier. Cependant, dans certains cas, le DataContext est pas accessible: il se passe pour les éléments qui ne font pas partie du visuel ou de l'arborescence logique. Il peut être très difficile de lier une propriété sur les éléments...
Illustrons avec un exemple simple: nous voulons afficher une liste de produits dans un DataGrid. Dans la grille, nous voulons être en mesure d'afficher ou de masquer la colonne de Prix basé sur la valeur d'un ShowPrice propriété exposée par le ViewModel. L'approche évidente est de se lier à la Visibilité de la colonne à la ShowPrice propriété:
Malheureusement, la modification de la valeur de ShowPrice n'a aucun effet, et la colonne est toujours visible... pourquoi? Si l'on regarde la fenêtre de Sortie de Visual Studio, nous avons remarqué la ligne suivante:
Nous pouvons essayer de tordre le contraignant à obtenir le résultat souhaité, par exemple par la définition de la RelativeSource à la grille de lui-même:
Ou nous pouvons ajouter une Case à cocher lié à ShowPrice, et d'essayer de lier la colonne de la visibilité à la propriété IsChecked en spécifiant le nom de l'élément:
Mais aucune de ces solutions ne semble fonctionner, on obtient toujours le même résultat...
À ce point, il semble que la seule approche viable serait de changer la colonne de visibilité dans le code-behind, qui nous préférons généralement à éviter lors de l'utilisation du pattern MVVM... Mais je ne vais pas abandonner si tôt, du moins pas tout il y a d'autres options à considérer
La solution à notre problème est en fait assez simple, et prend avantage de la Gelé de la classe. Le principal but de ce cours est de définir des objets qui ont une modifiables et un état en lecture seule, mais ce qui est intéressant dans notre cas, c'est que Freezable objets peuvent hériter le DataContext, même quand ils ne sont pas dans le visuel ou l'arborescence logique. Je ne connais pas le mécanisme exact qui permet à ce problème, mais nous allons en profiter pour faire notre travail de liaison...
L'idée est de créer une classe (je l'ai appelé BindingProxy pour des raisons qui devrait devenir évident très vite) qui hérite Gelé et déclare une dépendance de Données de propriété:
On peut alors déclarer une instance de cette classe dans les ressources de la grille de données, et la liaison de Données à la propriété DataContext:
La dernière étape consiste à spécifier cette BindingProxy objet (facilement accessible avec StaticResource) comme la Source de la liaison:
Noter que le chemin de liaison a été précédé par “Données”, car le chemin est maintenant par rapport à la BindingProxy objet.
La liaison fonctionne maintenant correctement, et la colonne est correctement affiché ou masqué sur la base de la ShowPrice propriété.