Search code examples
c#wpfcontextmenuitemscontrolcommandbinding

WPF Command Binding of ContextMenu Item inside ItemsControl


My Application consists of a MainWindow with a ContentControl and I change the ViewModel depending on the selected menu.

One of the UserControls I display as content contains the following WrapPanel:

<UserControl ...>
    <Grid>
        <WrapPanel>
            <ItemsControl ItemsSource="{Binding Connections}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Command="{Binding DataContext.ConnectionSelectCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                                CommandParameter="{Binding}"
                                FocusManager.FocusedElement="{Binding ElementName=InstanceName}"
                                Style="{DynamicResource DashboardButton}">
                            <TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding Name}" />
                            <Button.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Header="Delete"
                                              Command="{Binding ConnectionRemoveCommand}"
                                              CommandParameter="{Binding}" />
                                </ContextMenu>
                            </Button.ContextMenu>
                        </Button>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </WrapPanel>
    </Grid>
</UserControl>

The Command on the ContextMenu doesn't work because it tries to call ConnectionRemoveCommand on the Connection object instead of the ConnectionViewModel which is the DataContext of the UserControl.

How do I bind the Command to the ConnectionViewModel with the CommandParameter being the Connection object?


Solution

  • If you bind the Tag property of the Button to the DataContext of the ItemsControl, you could then bind to it using the PlacementTarget of the ContextMenu:

    <Button Command="{Binding DataContext.ConnectionSelectCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
            CommandParameter="{Binding}"
            FocusManager.FocusedElement="{Binding ElementName=InstanceName}"
            Style="{DynamicResource DashboardButton}"
            Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ItemsControl}}">
        <TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding Name}" />
        <Button.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Delete"
                        Command="{Binding PlacementTarget.Tag.ConnectionRemoveCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
                        CommandParameter="{Binding}" />
            </ContextMenu>
        </Button.ContextMenu>
    </Button>