2010-04-18 10 views
5

J'essaie de faire fonctionner ma première application WPF à l'aide de MVVM, et j'ai rencontré un petit problème de liaison.WPF: Définition de DataContext d'un contrôle UserControl avec la liaison ne fonctionnant pas en XAML

La configuration est que j'ai vue & viewmodel qui contient les détails de l'utilisateur (le parent), et d'essayer de garder les choses simples que j'ai mis une partie de ce point de vue dans une vue séparée & viewmodel (l'enfant). La vue enfant est définie en tant que UserControl.

Le problème que je rencontre est de savoir comment définir le DataContext de la vue enfant (UserControl). Mon parent ViewModel a une propriété qui expose l'enfant ViewModel, comme ceci:

class ParentViewModel: INotifyPropertyChanged 
{ 
    public ChildViewModel childViewModel { get; set; } 
    //... 
} 

Dans le XAML pour moi parent (qui a son DataContext ensemble à la ParentViewModel), j'essaie de régler le DataContext de la vue enfant comme suit:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Cependant, cela ne fonctionne pas. Le DataContext de la vue enfant est défini sur le même DataContext que la vue parent (c'est-à-dire le ParentViewModel), comme si je ne le définissais pas du tout. J'ai aussi tenté de mettre le DataContext chez l'enfant lui-même voir, ce qui ne fonctionne pas aussi:

<UserControl x:Class="DietRecorder.Client.View.ChildView" 
    DataContext="childViewModel" 

J'ai trouvé deux façons de contourner cela. De l'avis des enfants, je peux lier tout en incluant le ChildViewModel dans le chemin:

<SomeControl Visibility="{Binding Path=childViewModel.IsVisible}"> 

mais je ne veux pas le point de vue des enfants d'avoir ce niveau de conscience de la hiérarchie. Réglage du DataContext dans le code fonctionne aussi - cependant, je dois le faire après avoir montré la vue parent, sinon le DataContext se juste écrasé quand je l'appelle Show():

parentView.Show(); 
parentView.ChildView.DataContext = parentViewModel.childViewModel; 

Ce code me fait aussi mal à l'aise, ce avec la violation de LOD et tout.

Il est juste le DataContext qui semble être le problème - je peux lier d'autres choses chez l'enfant, par exemple, j'essayé lier le FontSize à une propriété int juste pour le tester:

<views:ChildView 
    x:Name="ChildView" 
    FontSize="{Binding Path=someVal}"/> 

Et que les travaux bien.

Mais je suis sûr que la liaison du DataContext devrait fonctionner - j'ai vu des exemples similaires de ce genre de chose. Ai-je manqué quelque chose d'évident ici? Y at-il une raison pour que cela ne fonctionne pas? Y a-t-il une faute d'orthographe quelque part? (J'ai renommé les choses pour votre bénéfice afin que vous ne puissiez pas m'aider de toute façon).

Toutes les pensées sont les bienvenues.

Modifier

Revoir ce code encore une fois, il semble que je l'ai fait une erreur quelque part, comme le XAML suivant dans la vue parent ne semble maintenant travailler:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Je suis Je ne sais pas pourquoi je ne pouvais pas le faire fonctionner à l'origine, ou ce que j'ai pu changer pour le faire fonctionner. Peut-être était-ce le problème INotifyPropertyChanged comme le suggère l'une des réponses. Eh bien, en avant et en haut ..

Répondre

2

Je suppose que c'est parce que la propriété childViewModel ne déclenche pas l'événement PropertyChanged. Lorsque la liaison est évaluée, il est possible que cette propriété soit null (dans ce cas, le DataContext reviendra juste à celui du parent). Lorsque le modèle childViewModel est instancié plus tard, aucun événement PropertyChanged n'est déclenché et la liaison n'est jamais informée qu'il existe désormais un DataContext.

Essayez d'augmenter l'événement PropertyChanged dans la propriété childViewModel.

Cheers, Laurent

+0

Bonne pensée, mais pas de joie j'ai peur. Je pensais que cela pourrait être quelque chose à voir avec la commande, mais l'enfant viewmodel devrait être disponible quand la liaison se produit - et cela fonctionne quand je définis la taille de la police en utilisant la propriété int, qui arrive en même temps. t utilisez PropertyChanged. –

2

je cherchais la même chose et je trouve une façon de le faire. Au fond, je lié DataContext de l'enfant à la DataContext de certains parents (la fenêtre) en utilisant

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

où j'ai mis x:Name="_topLevel" sur un certain contrôle parent (la fenêtre).

J'ai essayé d'utiliser RelativeSource/FindAncestor au lieu de ElementName mais cela n'a pas fonctionné - mais c'était probablement ma faute. Se sent comme un hack pour moi, mais mieux que la liaison au modèle de vue de niveau supérieur.

+0

Bien que je ne l'ai pas essayé, cela devrait fonctionner, donc je vais vous donner +1 pour l'effort après tout ce temps - mais cette solution a le même problème que l'une des solutions que j'ai suggéré ci-dessus, qui est que l'enfant connaît le parent. C'est soit juste une mauvaise odeur ou un vrai problème, selon que vous utilisez l'enfant dans différentes vues parentales ou non. Lors de la vérification de mon code pour cette réponse, j'ai découvert que cela fonctionne maintenant, même si je ne suis pas sûr de savoir pourquoi - voir la modification pour plus de détails. –

2

Ceci n'est pas une réponse à la question, mais pourrait aider les autres dans les mêmes circonstances.

je frappe exactement ce problème et a constaté que la

parentView.ChildView.DataContext = parentViewModel.childViewModel; 
approche

a travaillé (même si je trouve que ça a marché avant de faire Show()), mais avait les mêmes scrupules à ce sujet que le questionneur d'origine si essayé le

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

approche, qui semblait également fonctionner. Mais j'ai ensuite essayé de revenir au code original et à l'original XAML, et maintenant tout à coup, ça a aussi fonctionné. Cela reflète le comportement du questionneur original où l'auteur pensait avoir fait une erreur quelque part alors que le XAML semblait commencer à fonctionner sans raison apparente. Le seul changement que je peux voir est que Visual Studio montre maintenant des exemples de données dans le contrôle UserControl au moment du design, donc il a mis en cache des données exemple quelque part, et cela semble le faire fonctionner. Je ne suis pas sûr de savoir lequel des deux changements a causé cela, malheureusement. L'apparition d'exemples de données me permet de me demander si le problème est lié à l'utilisation de d: DataContext, que j'ai dans les fichiers XAML parent et enfant, mais ce n'est que de la spéculation.

Questions connexes