web-dev-qa-db-fra.com

À quoi sert DataContext?

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?

33
Eugene Strizhok

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?

91
Rachel

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 un DataContext de l'élément le plus proche lors de la traversée dans le , définissant les propriétés ElementName et RelativeSource dans l'objet Binding.

Exemple détaillé sur CodeProject: http://www.codeproject.com/Articles/321899/DataContext-in-WPF

3
Cornel Marian

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.

1
CodeNaked

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}"/>
1
H.B.