WPF: Binding a Property to a Custom UserControl
I have the following problem in wpf:
I defined a custom control (in a namespace test) containing a textbox (and a few other controls only showing the relevant xaml parts):
<UserControl (...)
DataContext="{Binding RelativeSource={RelativeSource Self}}"
name="Spinbox">
(...)
<StackPanel Orientation="Horizontal">
<TextBox x:Name="tbText" (...)>
<TextBox.Text>
<Binding Path="Value" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:ValidateValue MinVal="0" MaxVal="1" />
</Binding.ValidationRules>
<Binding.NotifyOnValidationError>true</Binding.NotifyOnValidationError>
</Binding>
</TextBox.Text>
</TextBox>
(...)
In the main window file, I am using this player:
<Test:SpinBox x:Name="tbTestSpinbox" Value="{Binding Path=TheValue}"
MinValue="0" MaxValue="150">
<Test:SpinBox.Behavior>
<Controls:SpinBoxNormalBehavior />
</Test:SpinBox.Behavior>
</Test:SpinBox>
In the code behind, I've defined TheValue:
private double theValue;
public Window1()
{
InitializeComponent();
TheValue = 10;
}
public double TheValue
{
get { return theValue; }
set
{
theValue = value;
NotifyPropertyChanged("TheValue");
}
}
/// <summary>
/// Occurs when a property value changes
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
When I try to run this application, I get a message in the output window:
System.Windows.Data Error: 39 : BindingExpression path error: 'TheValue' property not found on 'object' ''SpinBox' (Name='tbTestSpinbox')'. BindingExpression:Path=TheValue; DataItem='SpinBox' (Name='tbTestSpinbox'); target element is 'SpinBox' (Name='tbTestSpinbox'); target property is 'Value' (type 'Double')
And the spinbox is not populated with a value of 10, but the default is 0.
Does anyone have an idea how to make sure the value is displayed correctly?
You set UserControl DataContext to your XAML:
<UserControl (...)
DataContext="{Binding RelativeSource={RelativeSource Self}}"
... so later when you say this:
<Test:SpinBox x:Name="tbTestSpinbox" Value="{Binding Path=TheValue}"
MinValue="0" MaxValue="150">
the Value binding looks for the TheValue property on the SpinBox itself.
Instead of using the DataContext, change the bindings inside the UserControl to bind it to the control itself. I usually do this by giving the entire UserControl a XAML name:
<UserControl x:Name="me">
and then using element binding:
<TextBox.Text>
<Binding Path="Value"
ElementName="me"
UpdateSourceTrigger="PropertyChanged">
Unless otherwise noted, the binding path always refers to the DataContext. Therefore, in your window constructor, you must add this statement:
this.DataContext = this;