2012-06-13 3 views
5

Avoir le XAML ci-dessous MainWindow.xaml:datacontext

<Window x:Class="TestDependency.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition></RowDefinition> 
     <RowDefinition></RowDefinition> 
     <RowDefinition></RowDefinition> 
    </Grid.RowDefinitions> 
    <Label Name="someLabel" Grid.Row="0" Content="{Binding Path=LabelText}"></Label> 
    <Button Grid.Row="2" Click="Button_Click">Change</Button> 
    </Grid> 
</Window> 

Et le code suivant derrière dans MainWindow.xaml.cs:

public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register("LabelText", typeof(String), typeof(MainWindow)); 

public int counter = 0; 

public String LabelText 
{ 
    get 
    { 
    return (String)GetValue(LabelTextProperty); 
    } 

    set 
    { 
    SetValue(LabelTextProperty, value); 
    } 
} 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    LabelText = "Counter " + counter++; 
} 

j'aurais pensé que le défaut DataContext est le code derrière. Mais je suis obligé de spécifier le DataContext. Quels sont les DataContext par défaut?Null? J'aurais pensé que le code derrière aurait été (comme c'est le même cours).

Et comme dans cet exemple, je suis en utilisant le code sous-jacent de modifier le contenu de l'étiquette, pourrais-je utiliser directement:

someLabel.Content = "Counter " + counter++; 

j'attendre à ce que le code étant derrière, il ne devrait pas avoir le problème de mise à jour de l'interface utilisateur que vous avez si le DataContext est dans une classe différente.

Répondre

5

Oui, la valeur par défaut de DataContext est null, voici comment il est déclaré dans FrameworkElement classe -

public static readonly DependencyProperty DataContextProperty = 
    DependencyProperty.Register("DataContext", typeof(object), 
    FrameworkElement._typeofThis, 
    (PropertyMetadata) new FrameworkPropertyMetadata((object)null, 
     FrameworkPropertyMetadataOptions.Inherits, 
     new PropertyChangedCallback(FrameworkElement.OnDataContextChanged))); 

FrameworkPropertyMetadata prend le premier paramètre par défaut la valeur de la propriété.

Comme il est hérité par tous les contrôles enfants DataContext reste null sauf si vous spécifiez le contexte de données de fenêtre.

et vous pouvez utiliser someLabel.Content = "Counter " + counter++; dans codebehind pour définir le contenu des étiquettes; en tant que tel, il est parfaitement bien d'accéder à vos contrôles dans le code derrière.

3

Étant donné que vous liez une propriété Label, sauf si vous spécifiez une autre source de liaison, le moteur de liaison suppose en quelque sorte que LabelText est une propriété de cette classe. Il ne peut pas déterminer par magie que parce que le Label est un descendant d'un MainWindow la source de liaison devrait être cette fenêtre, c'est pourquoi vous devez le déclarer explicitement.

Il est important de noter que les concepts de « contexte de données » et « source de liaison » sont distincts: DataContext est une façon pour spécifier la source de liaison, mais there arealsoothers.

+0

Je pense cependant que la liaison/datacontext est héritée du parent lorsqu'elle n'est pas spécifiée. Sinon, définir le datacontext sur la classe de la fenêtre ne produira toujours pas de résultat. –

+0

@MiyamotoAkira: Bien sûr, c'est hérité (la documentation de 'DataContext' le dit aussi). Mais pourquoi vous attendez-vous à ce que 'MainWindow' soit le' DataContext' de n'importe quoi par défaut? Le moteur de liaison ne peut pas lire dans votre esprit. – Jon

+1

Je suppose que je vois MainWindow comme le sommet de la hiérarchie pour ce programme. Mais alors, je ne sais pas ce que wpf fait sous le capot (encore :-)), et il y a probablement d'autres choses en plus. –