How can I ensure that the Value
dependency property of my two UserControls
is consistently updated in my MainWindow
when I make changes to the property in one of the controls?
Control1:
<UserControl x:Class="ControlBining.Control1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}" Width="100"/>
</Grid>
</UserControl>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(string),
typeof(Control1)
);
public string Value
{
get => (string)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
Control2:
<UserControl x:Class="ControlBining.Control2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ControlBining"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</Grid>
</UserControl>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(string),
typeof(Control2)
);
public string Value
{
get => (string)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
MainWindow:
<Window x:Class="ControlBining.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ControlBining"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<local:Control1 Width="100" x:Name="Control1" Value="10"/>
<local:Control2 Width="100" Value="{Binding ElementName=Control1, Path=Value}"/>
</StackPanel>
</Window>
The UserControl should not set its own DataContext, because doing so breaks any DataContext based Bindings of its dependency propertises. Instead, use a RelativeSource Binding in its XAML:
<UserControl ...>
<Grid>
<TextBox Text="{Binding Value,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</Grid>
</UserControl>
If you want to update the Value
property while you are typing into the TextBox, also set this:
<TextBox Text="{Binding Value,
RelativeSource={RelativeSource AncestorType=UserControl},
UpdateSourceTrigger=PropertyChanged}"/>
When you also want to type into Control2, make the Value Binding TwoWay:
<local:Control2 Value="{Binding ElementName=Control1, Path=Value, Mode=TwoWay}"/>
or make the Value property bind TwoWay by default:
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
nameof(Value), typeof(string), typeof(Control2),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));