Reputation: 772
I've got some XAML like the following:
<UserControl x:Class="Foo">
<UserControl.Resources>
<ContextMenu x:Key="ContextMenu1">
<MenuItem Header="Command 1a"/>
<MenuItem Header="Command 1b"/>
</ContextMenu>
<ContextMenu x:Key="ContextMenu2">
<MenuItem Header="Command 2a"/>
<MenuItem Header="Command 2b"/>
</ContextMenu>
</UserControl.Resources>
<DockPanel>
<TreeView>
<TreeView.Resources>
<DataTemplate DataType="{x:Type Type1}">
<StackPanel ContextMenu="{StaticResource ContextMenu1"}/>
</DataTemplate>
<DataTemplate DataType="{x:Type Type2}">
<StackPanel ContextMenu="{StaticResource ContextMenu2"}/>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</DockPanel>
</UserControl>
and a code behind similar to the following:
public class Type1 {
public void OnCommand1a() {}
public void OnCommand1b() {}
}
public class Type2 {
public void OnCommand2a() {}
public void OnCommand2b() {}
}
What do I need to do so that clicking the respective items on the menus calls the corresponding function?
If I add:
Command="{Binding Path=OnCommand1a}" CommandTarget="{Binding Path=PlacementTarget}"
etc then at runtime I get errors about how OnCommand1a is not a property. Some searching suggests this has something to do with a RoutedUIEvent, but I don't really understand what that's about.
If I use
Click="OnCommand1a"
then it looks for OnCommand1a() on the UserControl instead of on the type that is bound to the DataTemplate.
What is the standard way of dealing this?
Upvotes: 0
Views: 934
Reputation: 946
First of all you need a class that extends ICommand. You can use this:
public class DelegateCommand : ICommand
{
private readonly Action<object> executeMethod = null;
private readonly Func<object, bool> canExecuteMethod = null;
public event EventHandler CanExecuteChanged
{
add { return; }
remove { return; }
}
public DelegateCommand(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
{
this.executeMethod = executeMethod;
this.canExecuteMethod = canExecuteMethod;
}
public bool CanExecute(object parameter)
{
if (canExecuteMethod == null) return true;
return this.canExecuteMethod(parameter);
}
public void Execute(object parameter)
{
if (executeMethod == null) return;
this.executeMethod(parameter);
}
}
Then, in your class Type1 you have to declare this:
public DelegateCommand OnCommand1a {get; private set;}
and set it in your Type1 constructor in this way:
OnCommand1a = new DelegateCommand(c => Cmd1a(), null);
where Cmd1a is:
private void Cmd1a()
{
//your code here
}
Finally, in your xaml:
Command="{Binding Path=OnCommand1a}"
Upvotes: 2