Comme suite à la question Lier DataContext à une autre propriété dans WPF .
À la toute fin de la recherche, j'ai été très surpris de découvrir que lorsque l'on écrit quelque chose comme ça:
<Label Content="{Binding Path=Name}" />
Le DataContext
contre lequel la propriété Content
est liée est du contrôle Label
lui-même! Le fait qu'il fonctionne toujours est dû à l'héritage par défaut de la valeur DataContext du parent le plus proche.
Mais si vous avez cette étiquette enveloppée dans un contrôle personnalisé et que vous ne voulez pas lier vos données à la propriété DataContext
de ce contrôle, vous aimeriez plus probablement avoir:
<Controls:SearchSettings Settings="{Binding Path=Settings}" />
Et voilà. Maintenant, vous devez définir Settings
comme DataContext
pour le contrôle SearchSettings
, pour Label
à l'intérieur pour se lier, mais vous ne pouvez pas, car cela déclencher une nouvelle liaison de la propriété Settings
.
Je ne vois pas l'intérêt de mélanger les propriétés de liaison en utilisant différentes sources: DataContext
, par ElementName
, etc. Alors pourquoi utiliserais-je DataContext
?
Quand tu écris
<Label name="myLabel" Content="{Binding Path=Name}" />
vous vous liez à myLabel.DataContext.Name
et non à myLabel.Name
.
Le XAML dans WPF est juste une jolie interface utilisateur pour afficher et interagir avec les données réelles, autrement connu sous le nom de DataContext
. Le but des autres sources de liaison (RelativeSource
, ElementName
, etc.) est de pointer vers une autre propriété qui n'existe pas dans le DataContext
du contrôle en cours
Supposons maintenant de définir myWindow.DataContext = new ClassA();
. Maintenant, les données que la fenêtre affiche sont ClassA
. Si ClassA
possède une propriété appelée Name
, je pourrais écrire une étiquette et la lier à Name
(comme votre exemple), et quelle que soit la valeur stockée dans ClassA.Name
s'afficherait.
Supposons maintenant que ClassA
possède une propriété ClassB
et que les deux classes aient une propriété appelée Name
. Voici un bloc de XAML qui illustre le but du DataContext, et un exemple de la façon dont un contrôle ferait référence à une propriété qui ne se trouve pas dans son propre DataContext
<Window x:Name="myWindow"> <!-- DataContext is set to ClassA -->
<StackPanel> <!-- DataContext is set to ClassA -->
<!-- DataContext is set to ClassA, so will display ClassA.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassA, however we are setting it to ClassA.ClassB -->
<StackPanel DataContext="{Binding ClassB}">
<!-- DataContext is set to ClassB, so will display ClassB.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassB, but we are binding to the Window's DataContext.Name which is ClassA.Name -->
<Label Content="{Binding ElementName=myWindow, Path=DataContext.Name}" />
</StackPanel>
</StackPanel>
</Window>
Comme vous pouvez le voir, le DataContext est basé sur les données qui se trouvent derrière l'objet d'interface utilisateur.
Mise à jour: Je vois cette question si souvent des nouveaux utilisateurs de WPF que j'ai développé cette réponse dans un article sur mon blog: Qu'est-ce que c'est " DataContext "dont vous parlez?
De CodeProject par kishore Gaddam:
DataContext
est l'un des concepts les plus fondamentaux de la liaison de données. L'objet Binding doit obtenir ses données quelque part, et il existe plusieurs façons de spécifier la source des données, comme l'utilisation de la propriété Source directement dans la liaison, en héritant unDataContext
de l'élément le plus proche lors de la traversée dans le , définissant les propriétésElementName
etRelativeSource
dans l'objet Binding.
Exemple détaillé sur CodeProject: http://www.codeproject.com/Articles/321899/DataContext-in-WPF
Dans ce cas particulier, vous pouvez faire:
<Controls:SearchSettings DataContext="{Binding Path=Settings}" Settings="{Binding}" />
En supposant que vous souhaitez que tout ce qui peut être contenu dans SearchSettings utilise les paramètres comme contexte de données. Fondamentalement, le DataContext affecte l'élément lui-même et tous les descendants qui ne le remplacent pas explicitement.
Dans la plupart des cas, vous faites voulez vous lier au DataContext, dans certains modèles sur ItemsControls, c'est le seul moyen de se lier à l'élément actuellement par exemple. D'autres liaisons au DataContext sont agréables à écrire et à lire car elles sont concises.
Dans votre exemple, vous pouvez toujours définir le DataContext, il vous suffit de modifier la liaison sur les paramètres respectivement:
<Controls:SearchSettings DataContext="{Binding Settings}" Settings="{Binding}"/>