2010-07-16 5 views
10

J'ai un UserControl que je veux participer à la liaison de données. J'ai configuré les propriétés de dépendance dans le contrôle utilisateur, mais je n'arrive pas à le faire fonctionner.Liaison de données à un UserControl dans WPF

L'UC affiche le texte correct lorsque je l'appelle avec du texte statique (par exemple BlueText = "ABC"). Lorsque j'essaie de le lier à une propriété publique locale, il est toujours vide.

<src:BlueTextBox BlueText="Feeling blue" />   <!--OK--> 
<src:BlueTextBox BlueText="{Binding Path=MyString}" /> <!--UserControl always BLANK!--> 
<TextBox Text="{Binding Path=MyString}" Width="100"/> <!--Simple TextBox Binds OK--> 

J'ai fait bouillir le code jusqu'à l'exemple simplifié suivant. Voici le XAML du UserControl:

<UserControl x:Class="Binding2.BlueTextBox" ... 
    <Grid> 
     <TextBox x:Name="myTextBox" Text="{Binding BlueText}" Foreground="Blue" Width="100" Height="26" /> 
    </Grid> 

Voici le code derrière du UserControl:

public partial class BlueTextBox : UserControl 
{ 
    public BlueTextBox() 
    { 
     InitializeComponent(); 
     DataContext = this; // shouldn't do this - see solution 
    } 

    public static readonly DependencyProperty BlueTextProperty = 
     DependencyProperty.Register("BlueText", typeof(string), typeof(BlueTextBox)); 

    public string BlueText 
    { 
     get { return GetValue(BlueTextProperty).ToString(); } 
     set { SetValue(BlueTextProperty, value.ToString()); } 
    } 

Cela semble que cela devrait être très facile, mais je ne peux pas le faire fonctionner. Merci de votre aide!

Plus d'infos: Quand j'ai essayé le correctif proposé par Eugene, j'ai remarqué un comportement particulier. J'ai ajouté un PropertyChangedCallback aux métadonnées; Cela me permet de regarder la valeur de BlueText se mettre en place. Lorsque la chaîne est définie sur une valeur statique (= "feeling blue"), l'événement PropertyChanged se déclenche. Le cas de liaison de données ne déclenche pas PropertyChanged. Je pense que cela signifie que la valeur liée aux données n'est pas envoyée à UserControl. (Je pense que le constructeur n'est pas appelé dans le cas statique)

Solution: Les problèmes ont été correctement identifiés par Arcturus et jpsstavares. D'abord, j'ai écrasé la liaison de données quand est défini DataContext = this dans le constructeur du contrôle. Cela a empêché l'établissement de la valeur liée aux données. J'ai aussi dû nommer le contrôle x: Name = root, et spécifier le Binding ElementName = root int le XAML. Pour obtenir la liaison TwoWay, j'avais besoin de régler Mode = TwoWay dans l'appelant. Voici le code correct:

<src:BlueTextBox BlueText="{Binding Path=MyString, Mode=TwoWay}}" /> <!--OK--> 

Maintenant, le XAML dans le UserControl:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="root"... 
    <Grid> 
     <TextBox x:Name="myTextBox" Text="{Binding ElementName=root, Path=BlueText}" Foreground="Blue" Width="100" Height="26" /> 
    </Grid> 

Enfin j'ai enlevé DataContext = ceci dans le constructeur de la UserControl.

public BlueTextBox() 
    { 
     InitializeComponent(); 
     //DataContext = this; -- don't do this 
    } 

Merci à tous pour votre aide!

Répondre

11

Vous définissez le DataContext dans le contrôle de lui-même, ainsi le DataContext écrasant lors de l'utilisation de ce contrôle dans d'autres contrôles. Prendre votre fixation comme par exemple dans votre situation:

<src:BlueTextBox BlueText="{Binding Path=MyString}" /> 

Une fois chargé et tout le DataContext est réglé, il va chercher le chemin MaChaîne dans votre contrôle chose BlueTextBox en raison de vous mettre DataContext à lui. Je suppose que ce n'est pas de cette façon que vous vouliez que ça marche;).

Solution:

Modifier le texte liant l'un des 2 liaisons:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:BlueTextBox}}, Path=BlueText} 

ou

Nom racine de votre commande (ou quelque chose comme ça)

<UserControl x:Name="Root" 

{Binding ElementName=Root, Path=BlueText} 

Et retirez le

DataContext = this; 

du constructeur de votre UserControl et il devrait fonctionner comme un charme ..

0

Peut-être que vous devez ajouter à votre propriété FrameworkPropertyMetadata où spécifier FrameworkPropertyMetadataOptions.AffectsRender et AffectsMeasure.

FrameworkPropertyMetadataOptions enumeration MSDN article

+0

Essayé paramétrez à la fois AffectsRender et AffectsMeasure, mais cela n'a pas eu d'effet. Merci. – RaoulRubin

2

Je pense que dans ce cas, vous devez définir la propriété ElementName dans la liaison. Quelque chose comme ceci:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="blueTextBox"... 
<Grid> 
    <TextBox x:Name="myTextBox" Text="{Binding ElementName=blueTextBox, Path=BlueText}" Foreground="Blue" Width="100" Height="26" /> 
</Grid> 
0

Je sais que c'est un vieux sujet, mais encore.

mentionner également le PropertyChangedCallback sur le UIPropertyMetadata lors de l'enregistrement de votre DP