I have a UserControl that I want to participate in data binding. I've set up the dependency properties in the user control, but can't get it work.
The uc displays the correct text when I call it with static text (e.g BlueText="ABC") . When i try to bind it to a local public property, it is always blank.
<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--> I've boiled the code down to the following simplified example. Here is the XAML of the UserControl:
<UserControl x:Class="Binding2.BlueTextBox" ... <Grid> <TextBox x:Name="myTextBox" Text="{Binding BlueText}" Foreground="Blue" Width="100" Height="26" /> </Grid> Here is the code behind of the 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() ); } } This seems like it should be really easy, but I can't make it work. Thanks for your help!
More info: When i was trying the fix suggested by Eugene, I noticed some peculiar behavior. I added a PropertyChangedCallback to the metadata; this allows me to watch the value of BlueText getting set. When setting the string to a static value (="feeling blue") the PropertyChanged event fires. The data binding case does not fire PropertyChanged. I think this means the data-bound value is not getting sent to the UserControl. (I think the constructor does not get called in the static case)
Solution: The problems were correctly identified by Arcturus and jpsstavares. First, I was overwriting the data binding when is set DataContext=this in the constructor of the control. This prevented the data bound value from getting set. I also had to name the control x:Name=root, and specify the Binding ElementName=root int the XAML. To get the TwoWay binding, I needed to set Mode=TwoWay in the caller. Here is the correct code:
<src:BlueTextBox BlueText="{Binding Path=MyString, Mode=TwoWay}}" /> <!--OK--> Now the XAML in the 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> Finally I removed the DataContext=this in the constructor of the UserControl.
public BlueTextBox() { InitializeComponent(); //DataContext = this; -- don't do this } Thanks everyone for the tremendous help!