My View Contains a Button
and a UserControl
. The UserControl
also contains a Button
. Both, Button1 in my View and Button2 in my UserControl
should call the same method in the ViewModel.
Therefore I need to 'inject' (don't know how to call it) the RelayCommand
into the UserControl
. I thought it would be easy with dependency properties but i can't get it to work.
What i tried:
The UserControl
contains a dependency property which is set in the XAML Code of the View containing the UserControl
:
UserControl Code:
public const string LoadDataCommandPropertyName = "LoadDataCommand";
public Action LoadDataCommand
{
get
{
return (Action)GetValue(LoadDataCommandProperty);
}
set
{
SetValue(LoadDataCommandProperty, value);
}
}
public static readonly DependencyProperty LoadDataCommandProperty = DependencyProperty.Register(
LoadDataCommandPropertyName,
typeof(Action),
typeof(GridViewPersistenceController),
new UIPropertyMetadata());
View Xaml Code: (usage of the dp in the UserControl)
<customControls:MyUserControl Grid.Column="1"
x:Name="RadGridViewSettingsPersistenceControl"
GridControl="{Binding ElementName=RadGridView}"
LoadDataCommand="{Binding ActionTest}"
/>
The LoadDataCommand from the UserControl is bound to this property in the ViewModel
private const string ActionTestPropertyName = "ActionTest";
private Action actionTest;
public Action ActionTest
{
get
{
return this.actionTest;
}
set
{
this.RaisePropertyChanging(ActionTestPropertyName);
this.actionTest = value;
this.RaisePropertyChanged(ActionTestPropertyName);
}
}
The ActionTest property is initialized in the Constructor of the ViewModel
public MyViewModel()
{
this.ActionTest = new Action(this.LoadData);
}
The visual studio output window also gave me a binding error (which i don't understand)
System.Windows.Data Error: 40 : BindingExpression path error: 'ActionTest' property not found on 'object' ''MyUserControl' (Name='RadGridViewSettingsPersistenceControl')'. BindingExpression:Path=ActionTest; DataItem='MyUserControl' (Name='RadGridViewSettingsPersistenceControl'); target element is 'MyUserControl' (Name='RadGridViewSettingsPersistenceControl'); target property is 'LoadDataCommand' (type 'Action')
I found a workaround which is working but i don't like it. I set the LoadDataCommand in LoadedEvent of View codebehind. It looks messy to me and i feel i missed some important concepts.
//TODO: Dirty coding, fix me
private void MyView_OnLoaded(object sender, RoutedEventArgs e)
{
this.RadGridViewSettingsPersistenceControl.LoadDataCommand = new Action((this.DataContext as MyViewModel).LoadData);
}
Questions:
Command
/Action
defined in the ViewModel into a UserControl using xaml code in the View?As evident from the error:
'ActionTest' property not found on 'object' ''MyUserControl' (Name='RadGridViewSettingsPersistenceControl')'
binding engine is searching for property in control and not in your ViewModel. (by default it searches for property in DataContext of control and i suspect you have set DataContext of control to itself somewhere in your code)
Use RelativeSource to get DataContext of your UserControl which will be your ViewModel.
LoadDataCommand="{Binding DataContext.ActionTest,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl}}"
Also instead of creating DP of type Action
, use ICommand
and create ICommand in your ViewModel and bind to it.
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