2016-10-21 1 views
2

J'essaie (et j'échoue) de faire une liaison de données sur une propriété de dépendance dans xaml. Cela fonctionne très bien quand j'utilise du code derrière, mais pas dans xaml.La liaison XAML ne fonctionne pas sur la propriété de dépendance?

Le contrôle utilisateur est tout simplement un TextBlock qui se lient à la propriété de dépendance:

<UserControl x:Class="WpfTest.MyControl" [...]> 
    <TextBlock Text="{Binding Test}" /> 
</UserControl> 

Et la propriété de dépendance est une chaîne simple:

public static readonly DependencyProperty TestProperty 
= DependencyProperty.Register("Test", typeof(string), typeof(MyControl), new PropertyMetadata("DEFAULT")); 

public string Test 
{ 
    get { return (string)GetValue(TestProperty); } 
    set { SetValue(TestProperty, value); } 
} 

J'ai un bien régulier avec la mise en œuvre habituelle de INotifyPropertyChanged dans la fenêtre principale.

private string _myText = "default"; 
public string MyText 
{ 
    get { return _myText; } 
    set { _myText = value; NotifyPropertyChanged(); } 
} 

Jusqu'ici tout va bien. Si je lie cette propriété à un TextBlock sur la fenêtre principale tout fonctionne très bien. Le texte se met à jour correctement si le MyText change et tout va bien dans le monde.

<TextBlock Text="{Binding MyText}" /> 

Cependant, si je fais la même chose sur mon contrôle utilisateur, rien ne se passe.

Et maintenant la partie amusante est que si je fais la même liaison dans le code derrière cela fonctionne!

TheControl.SetBinding(MyControl.TestProperty, new Binding 
{ 
    Source = DataContext, 
    Path = new PropertyPath("MyText"), 
    Mode = BindingMode.TwoWay 
}); 

Pourquoi cela ne fonctionne-t-il pas dans xaml?

+0

Afficher davantage de votre code XAML. Je soupçonne que si vous vous liez à {Binding}, vous constaterez que vous liez au mauvais contexte de données. – SledgeHammer

+0

Vous devez transmettre le nom de la propriété ("Test") en tant que premier paramètre à la méthode Register. Je ne pouvais pas trouver une surcharge qui reçoit un type comme premier paramètre. –

+0

Quel est le DataContext du MyControl?Cela pourrait être la MainWindow –

Répondre

7

La déclaration de propriété de dépendance doit ressembler à ceci:

public static readonly DependencyProperty TestProperty = 
    DependencyProperty.Register(
     "Test", typeof(string), typeof(MyControl), new PropertyMetadata("DEFAULT")); 

public string Test 
{ 
    get { return (string)GetValue(TestProperty); } 
    set { SetValue(TestProperty, value); } 
} 

La liaison en XAML doit définir l'instance de contrôle du UserControl comme l'objet source, par exemple en définissant la propriété de Manchettes RelativeSource:

<UserControl x:Class="WpfTest.MyControl" ...> 
    <TextBlock Text="{Binding Test, 
     RelativeSource={RelativeSource AncestorType=UserControl}}"/> 
</UserControl> 

également très important, jamais mis l'DataContext d'un UserControl dans son constructeur. Je suis sûr qu'il ya quelque chose comme

DataContext = this; 

Retirez-le, car il empêche effectivement hériter d'un DataContext de parent de l'UserConrol.

En fixant Source = DataContext dans la liaison dans le code derrière vous définissez explicitement une source de liaison, tandis que dans

<local:MyControl Test="{Binding MyText}" /> 

la source de liaison est implicitement le DataContext actuel. Cependant, DataContext a été défini par l'affectation dans le constructeur UserControl à UserControl lui-même et n'est pas le DataContext hérité (c'est-à-dire l'instance de modèle de vue) de la fenêtre.

+0

J'ai bien peur que ça ne marche pas. En passant, vous avez écrit exactement la même déclaration pour 'DependencyProperty' que ce qui est dans ma question. – Oliver

+0

Loin de * exactement les mêmes *. Dans votre question, vous avez oublié le nom de la propriété ("Test") et le mot-clé * new * sur PropertyMetadata. Ces détails sont importants! – Clemens

+0

omg, vous avez totalement raison! Je suis vraiment désolé. Je dois avoir collé le code incorrect. – Oliver