首页 > 解决方案 > 来自资源 ContextMenu 的命令不会触发

问题描述

我需要使用上下文菜单来重新启动基于数据网格的服务(上下文菜单应该将服务的名称作为命令参数发送)

ContextMenu 正确显示,但单击 MenuItems 不会触发命令(未到达断点),而是将上下文菜单直接设置为复选框,例如完美地触发命令。

最终,我想要的是在右键单击数据网格的任何项目时获取上下文菜单,单击菜单项应将名称列值或整个选定项目发送到 ViewModel 中的命令(然后从那里重新启动进程) .

这几天真的很头疼,如果你有任何提示......

我的数据网格:

<DataGrid x:Name="dgServices" HorizontalAlignment="Left" VerticalAlignment="Top" DockPanel.Dock="Top" Height="auto" HeadersVisibility="Row"
              AutoGenerateColumns="False" HorizontalGridLinesBrush="#FFC7E0EE" VerticalGridLinesBrush="#FFC7E0EE" SelectionMode="Single" BorderThickness="0"
              ItemContainerStyle="{StaticResource DefaultRowStyle}" ItemsSource="{Binding Source={StaticResource cvsServ}}">
            <DataGrid.GroupStyle>
                //GROUPSTYLE
            </DataGrid.GroupStyle>
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="30"/>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="373">
                </DataGridTextColumn>
                <DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="356"/>
            </DataGrid.Columns>
        </DataGrid>

Window.Resources 中的 ContainerStyle 和 ContextMenu:

<Window.Resources>
<ContextMenu  x:Key="RowMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
    <MenuItem Header="NULL" Command="{Binding restartService}"/>
    <MenuItem Header="NAME" CommandParameter="{Binding PlacementTarget.Name, RelativeSource={RelativeSource FindAncestor,AncestorType=ContextMenu}}" Command="{Binding restartService}"/>
    <MenuItem Header="ITEM" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource FindAncestor,AncestorType=ContextMenu}}" Command="{Binding restartService}"/>
    <MenuItem Header="ITEMS" CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource FindAncestor,AncestorType=ContextMenu}}" Command="{Binding restartService}"/>
</ContextMenu>

 <Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}">
    <Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
 </Style>

<CollectionViewSource x:Key="cvsServ" Source="{Binding services, UpdateSourceTrigger=PropertyChanged}">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Key" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

用于测试的复选框:

<CheckBox IsChecked="{Binding autoStart, Mode=TwoWay}">
                <Label Content="AutoStart"/>
                <CheckBox.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Edit" CommandParameter="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor,AncestorType=ContextMenu}}" Command="{Binding restartService}"/>
                        <!--<MenuItem Header="Edit" CommandParameter="{Binding ElementName=dgServices, Path=SelectedItem}" Command="{Binding restartService}"/>-->
                    </ContextMenu>
                </CheckBox.ContextMenu>
            </CheckBox>

视图模型:

    private DelegateCommand _restartService;
    public DelegateCommand restartService
    {
        get
        {
            return _restartService ?? (_restartService = new DelegateCommand(o => TestCommand(o), o => true));
            //return _restartService ?? (_restartService = new DelegateCommand(o => MessageBox.Show($"{o.ToString()}\n{o.GetType()}"), o => true));
            //return _restartService ?? (_restartService = new DelegateCommand(o => Process.Start(new ProcessStartInfo("C:\\Windows\\system32\\cmd.exe", "/c net start "+o.ToString()) { Verb = "runas" }), o => true));
        }

    private void TestCommand(object o)
    {
        MessageBox.Show(o?.GetType()?.ToString() ?? "NULL");
    }

标签: c#wpfmvvmcommandcontextmenu

解决方案


如果在 的视图模型中定义了命令属性,则可以将行的属性DataGrid绑定到:TagDataGrid

<Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}">
    <Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
    <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}" />
</Style>

...然后试试这个:

<MenuItem Header="NAME"
          Command="{Binding PlacementTarget.Tag.DataContext.restartService, RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}"
          CommandParameter="{Binding PlacementTarget.Tag.Name, RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}"/>

推荐阅读