Say I have a very simple UserControl that - for all intents and purposes - is nothing more than TextBox:
public partial class FooBox : UserControl
{
public static readonly DependencyProperty FooTextProperty =
DependencyProperty.Register("FooText", typeof(string), typeof(FooBox));
public FooBox()
{
InitializeComponent();
}
public string FooText
{
get { return textBlock.Text; }
set { textBlock.Text = value; }
}
}
<UserControl x:Class="Namespace.FooBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Grid>
<TextBlock x:Name="textBlock" />
</Grid>
</UserControl>
On the form it's declared as:
<local:FooBox FooText="{Binding Name}" />
The form's DataContext is set to an object that has a Name property. But this is not working for me. What am I missing?
The "get" and "set" parts of a property declaration in a DependencyProperty aren't actually called by the databinding system of WPF - they're there essentially to satisfy the compiler only.
Instead, change your property declaration to look like this:
public string FooText
{
get { return (string)GetValue(FooTextProperty); }
set { SetValue(FooTextProperty, value); }
}
... and your XAML to:
<UserControl ...
x:Name="me">
<Grid>
<TextBlock Text="{Binding FooText,ElementName=me}" />
</Grid>
</UserControl>
Now your TextBox.Text simply binds directly to the "FooText" property, so you can in turn bind the FooText property to "Name" just like you're currently doing.
Another way is to bind TextBlock.Text to a RelativeSource binding that finds the FooText property on the first ancestor of type "FooBox", but I've found that this is more complex than just giving the control an internal x:Name and using element binding.
Turns out the real problem is I was expecting the WPF framework to set my public property whereupon my code would respond to the changes and render according to the new value. Not so. What WPF does is call SetValue() directly and completely circumvents the public property. What I had to do was receive property change notifications using DependencyPropertyDescriptor.AddValueChanged and respond to that. It looks something like (inside the ctor):
var dpd = DependencyPropertyDescriptor
.FromProperty(MyDependencyProperty, typeof(MyClass));
dpd.AddValueChanged(this, (sender, args) =>
{
// Do my updating.
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With