【问题标题】:Command from Resources ContextMenu does not trigger来自资源 ContextMenu 的命令不会触发
【发布时间】:2019-11-18 10:59:06
【问题描述】:

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

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");
    }

【问题讨论】:

  • 您的命令是否在与services 集合相同的 ViewModel 中定义?还是在表示services 集合中的单独项目的视图模型中?
  • 试试这个:&lt;MenuItem Header="NAME" Command="{Binding PlacementTarget.DataContext.restartService, RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}"/&gt;
  • @mm8 这个也没有触发命令,是不是故意漏掉了命令参数?
  • @PavelAnikhouski 是的,该命令与收集服务在同一视图模型中定义
  • @Phoque:PlacementTarget.Type 是什么? Type 属性在哪里定义?

标签: c# wpf mvvm command contextmenu


【解决方案1】:

如果命令属性定义在DataGrid的视图模型中,您可以将行的Tag属性绑定到DataGrid

<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}}"/>

【讨论】:

  • 是的!实际上,这给出了数据网格本身的名称,但更改为 SelectedItem 我可以在我的命令中获取进程名称。非常感谢,您是否有一些我不知道的标签的文档
  • 为了将来参考,我在此处添加一个链接来解释您对 Tag 属性所做的操作spectrecoder.com/?p=51
猜你喜欢
  • 1970-01-01
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
相关资源
最近更新 更多