I have custom control that is being used in data template for an ItemsControl. I want to put a ContextMenu on each item and have it call the UserControl's View Model to process the command. Using the XAML below, I can get click events on the custom control to call the SelectedItemCommand in the user control view model. But, using similar syntax for the context menu fails. By default I get the view mode per each custom control. Any of the RelativeSource syntax value I use don't resolve to the user control's view model (RelativeSource Self).
What's the magic code?
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:MyCustomItem Width="Auto"
Command="{Binding DataContext.SelectedItemCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding}">
<controls:MyCustomItem.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
Header="Clear All" />
</ContextMenu>
</controls:MyCustomItem.ContextMenu>
</controls:MyCustomItem>
</DataTemplate>
</ItemsControl.ItemTemplate>
ContextMenu doesn't lie in same Visual Tree
as that of ItemsControl. Hence RelativeSource and ElementName won't work in Binding because they traverse Visual tree to found the source.
If you are using WPF 4.0 or higher you can use x:Reference
markup extension to bind with ItemsControl dataContext.
Set x:Name
on ItemsControl and bind using x:Reference
like this:
<ItemsControl x:Name="itemsControl">
....
<MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
Source={x:Reference itemsControl}}"
Header="Clear All" />
....
</ItemControl>
Also you can use Freezable BindingProxy
approach if you are targeting version lower than WPF 4.0. Refer to my answer over here for the approach.
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