Reputation: 902
Topic: How to prevent that the binding on a UserControl overrides the binding given by the upper (Main)Window using this UserControl.
I already read posts, and some books on that subject but I am still puzzled with binding mechanisms. Even in some specialized books the terms of DependencyProperty or AttachedProperty is barely mentioned. Microsoft documentation is good but somewhat bare.
This example is an extreme simplification of the BasketballRoster MVVM example of Head First C#
I have a usercontrol, a simple circle
...
xmlns:vm_nmspc="clr-namespace:BindingMCVE.ViewModel" >
<UserControl.Resources>
<vm_nmspc:my_usercontrol_vm x:Key="MyUserControlVM"/>
</UserControl.Resources>
<Grid>
<StackPanel DataContext="{DynamicResource ResourceKey=MyUserControlVM}" Height="100" Width="100">
<Ellipse Fill="{Binding my_color}" Height="50" Width="50"/>
</StackPanel>
</Grid>
And what I like is to provide a parameterless contructor my_usercontrol_vm() so that I can view my circle filled with red while I am working on the view of my UserControl.
For that I use an instance of the class my_usercontrol_vm inside the UserControlResources. Here I use the DynamicResource keyword ( I had first tested StaticResource )
class my_usercontrol_vm
{
public string my_color {get; set;}
public my_usercontrol_vm() : this("Red") { }
public my_usercontrol_vm(string color)
{
my_color = color;
}
}
Now I want to use several UserControl inside a (Main)Window, still using binding to see in "real time" the evolution of my view.
xmlns:vm_nmspc="clr-namespace:BindingMCVE.ViewModel" >
<Window.Resources>
<vm_nmspc:main_window_vm x:Key="MainWindowVM"/>
</Window.Resources>
<Grid>
<StackPanel DataContext="{DynamicResource ResourceKey=MainWindowVM}">
<view_nmspc:UserControl1 DataContext="{Binding usr_ctrl_1}"/>
<view_nmspc:UserControl1 DataContext="{Binding usr_ctrl_2}"/>
</StackPanel>
</Grid>
</Window>
And the ViewModel class dedicated to the MainWindow
class main_window_vm
{
public my_usercontrol_vm usr_ctrl_1 { get; set; }
public my_usercontrol_vm usr_ctrl_2 { get; set; }
public main_window_vm()
{
usr_ctrl_1 = new my_usercontrol_vm("Green");
usr_ctrl_2 = new my_usercontrol_vm("Blue");
}
}
Note that I am expecting to see GREEN and BLUE filled circles.
However what I get is red circles
I would have got green and blue circle I had not put a resource inside the UserControl
While using the debugger I can see that I am entering first the constructor of the class main_window_vm and after (2 times) the one of the class my_user_control_vm, so that both circles are finally red.
I know that at the present time I am maybe 10% aware of WPF but I thought that this way of doing would have been quite right. As last I am requesting that inside the MainWindow the UserControl1 control be bind to the property usr_ctrl_X of the class main_window_vm
Any advice welcome.
Best Regards.
NGI
Upvotes: 1
Views: 972
Reputation: 902
Following the answer of Charles Mager ( many thanks ), I post a reply on my own question so that everyone has the answer illustrated.
So charles adviced to put the DataContext into the UserControl and not the StackPanel
<UserControl x:Class="BindingMCVE.UserControl1"
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="100" d:DesignWidth="100"
xmlns:vm_nmspc="clr-namespace:BindingMCVE.ViewModel"
DataContext="{DynamicResource ResourceKey=MyUserControlVM}" >
<!--DataContext added above-->
<UserControl.Resources>
<vm_nmspc:my_usercontrol_vm x:Key="MyUserControlVM"/>
</UserControl.Resources>
<Grid>
<!--DataContext removed from StackPanel below-->
<StackPanel Height="100" Width="100">
<Ellipse Fill="{Binding my_color}" Height="50" Width="50"/>
</StackPanel>
</Grid>
</UserControl>
And here it is:
Upvotes: 0
Reputation: 26213
You are setting the DataContext
of your UserControl
, but this isn't used by your Ellipse
as this inherits the DataContext
of the StackPanel
. This doesn't change and will always be bound to your MyUserControlVM
resource.
You should remove DataContext="{DynamicResource ResourceKey=MyUserControlVM}"
from the StackPanel
. If you add this to the UserControl
then your binding should overwrite it. You could also use the blend design namespaces to set a design DataContext
that would only be used at design time.
Upvotes: 1