10
votes

La propriété DataContext de FrameworkElement n'hérite pas dans l'arbre d'élément

Bonjour WPF Pros au moins J'espère que certains d'entre vous lire ceci!

DataContext est une propriété sur FrameworkElement (classe de base pour tous les contrôles du WPF) et est implémentée comme une dépendanceProperty. Cela signifie que tous les éléments descendants de l'arborescence logique partagent le même DataContext.

donc le contenuControl doit le faire avec ses éléments descendants non?

J'ai un scénario où c'est pas le cas et j'aimerais savoir quelle est la cause de cette mauvaise conduite ?!

Que vous comprenez un peu plus à ce sujet s'il vous plaît lire ce fil (ne voulez pas tout copier ici) où le problème commence ...:

WPF: ne peut pas trouver la cible de déclenchement 'cc'. La cible doit apparaître avant tout setters, déclenche

et pour le dire dans Mots courts : Mes types de données dans le contenuControl ont un DataContext mort qui signifie qu'il n'y a rien à se lier, ce qui n'est pas réellement possible ...

Chaque élément en bas du contenuControl n'a rien défini dans la propriété DataContext ???


0 commentaires

4 Réponses :


23
votes

DataContext est une propriété sur FrameworkElement (classe de base pour tous Contrôles WPF) et est mis en œuvre en tant que DépendanceProperty. Cela signifie que tout le Éléments descendants dans le logique Tree partage le même DataContext.

Le fait que c'est une propriété de dépendance n'implique pas l'héritage ... il est vrai pour dataContext , mais seulement parce que la propriété de dépendance dispose du FramedProperTyTataTaOptions.Inshérite ses métadonnées.

Donc, le contenuControl devrait le faire avec ses éléments descendants non?

contentControl est un bit spécial: le DataContext de ses descendants (l'arborescence visuelle construite à partir du daTemplate ) est effectivement le Contenu du contentControl . Donc, si votre contentcontrol n'a pas de contenu, le DataContext à l'intérieur est null.


12 commentaires

Mon contenuControl a un DataContext comme PersonListViewModel, mais le problème semble être un nœud sur le contenu de contenu et sa propriété de contenu qui n'est pas définie et que le DataContext n'est pas non plus. Ok je comprends ta réponse bien que ça sonne toujours un peu étrange pour moi. Donc, la solution que Meleak m'a proposé n'était en fait pas de solution de contournement plutôt que la seule chose qu'il puisse faire / doit faire. Toute autre solution / opinion sur cette question?


Votre contentControl a un dataContext, mais a-t-il un contenu ?


Il n'y a pas de propriété "contenu" dans le contenuControl à l'aide de SNOOP. Dans xaml il y a ... ?? Un noeud bas il y a le programme de contenu qui a une propriété de contenu et qui est vide.


Par défaut Snoop n'extroude pas les propriétés définies sur leur valeur par défaut, vous pouvez les afficher avec le bouton "D". Quoi qu'il en soit, cela signifie probablement que le contenu est NULL, ce qui explique pourquoi vous n'avez pas de datacontext dans les descendants


Oui, le "D" en haut dans le coin de Snoop ... Vous étiez droit, le contenu est vide, donc pas de datacontext. La question est juste de savoir pourquoi la propriété de contenu est-elle vide?


Eh bien, peut-être parce que vous ne l'avez pas dit ... Je ne peux que faire des hypothèses depuis que vous n'avez pas publié le code


Ah désolé je pensais que vous savez que vous savez que le lien de l'autre thread avec Meleak: sendspace.com/file/a427u1 Est-ce que vous pouvez télécharger ce projet VS2010? Publier tout le code ici sera beaucoup prolly?


En ce qui concerne cette réponse acceptée, pourquoi est-ce le cas? Cela semble être un méchant GOTCHA pour lequel je ne vois aucune raison, mais je suis sûr qu'il y a une raison.


@ardave, je ne comprends pas votre question. Pourquoi c'est quoi le cas?


Pourquoi est-ce que c'est le cas que les conteneurs de contenu ont besoin de leur contenu à définir pour que leurs datacontextes aient une valeur, alors que de nombreuses autres entités WPF prennent en charge le héritage DataContext Direct?


@ardave, je suppose que si c'était le cas, cela causerait des problèmes de nidification avec des modèles de données implicites. Par exemple, supposons que vous disposez d'un fichier de données pour Type X (déclaré dans des ressources avec Type X comme clé, il est donc capté automatiquement dans ContentControls) et que DataTemplate contient un contenuControl. Si vous n'avez pas défini le contenu sur ce contenuControl, et que le fichier DataContext est hérité de contenu, cette contentControl utiliserait le même daTatemplate pour afficher son contenu, provoquant une nidification infinie ...


Quoi qu'il en soit, c'est probablement une décision de conception consciente qui pourrait avoir rien à voir avec l'explication ci-dessus ... vous devez demander à Microsoft pour les vraies raisons.



15
votes

Ceci a fonctionné pour moi: xxx

sans le contenu = "{Binding}" , le DataContext était NULL


1 commentaires

Ceci peut être légèrement simplifié à



0
votes

La dernière réponse (de Vincef) a travaillé pour moi aussi.

Je voulais montrer un UserControl en fonction de la valeur d'une propriété dans mon viewModel. J'ai donc fait un contentontrol avec des déclencheurs de style. En fonction de la valeur d'une propriété de liaison, la gâchette définit une plaquette de contenu spécifique contenant le spécifique UserControl.

L'UserControl a été montré à droite, mais son DataContext a toujours été null. Je devais donc définir le contexte du contenuControl sur: content = "{Binding}" Après cela, les Usercontrols ont fonctionné bien et avaient le même DataContext comme leur parent.

mon xaml ressemble à ça:

dans la partie Ressources J'ai défini deux dataMPates; Chacun pour chaque UserControl, je veux montrer. xxx

La partie où je montre que l'usercontrol en fonction d'une propriété est la suivante: xxx


0 commentaires

0
votes

Après avoir lu cette question et des réponses précédentes, je préfère utiliser contenuControl avec des données déclenchées de données telles que ceci:

Commandes qui seront définies comme contenu de contenuControl: P>

<ContentControl>
  <ContentControl.Style>
    <Style>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=Property}" Value="0">
                <Setter Property="Content" Value="{StaticResource ViewA}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=Property}" Value="1">
                <Setter Property="Content" Value="{StaticResource ViewB}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
  </ContentControl.Style>
</ContentControl>


0 commentaires