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!