Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting DataContext for ContextMenu in ItemsControl.DataTemplate

Tags:

wpf

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>
like image 961
doobop Avatar asked Jul 29 '14 16:07

doobop


1 Answers

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.

like image 118
Rohit Vats Avatar answered Nov 04 '22 04:11

Rohit Vats