c# - 如何在 WPF 上下文菜单项单击事件处理程序中引用右键单击对象?

标签 c# wpf event-handling contextmenu

在 WPF 应用程序中,有一个包含许多对象的 Grid(它们源自自定义控件)。我想使用上下文菜单对它们中的每一个执行一些操作:

   <Grid.ContextMenu>
     <ContextMenu>
       <MenuItem  Name="EditStatusCm" Header="Change status" Click="EditStatusCm_Click"/>
     </ContextMenu>                   
   </Grid.ContextMenu> 

但是在事件处理程序中我无法知道右键单击了哪个对象:

    private void EditStatusCm_Click(object sender, RoutedEventArgs e)
    {
        MyCustControl SCurrent = new MyCustControl();
        MenuItem menu = sender as MenuItem;
        SCurrent = menu.DataContext as MyCustControl; // here I get a run-time error
        SCurrent.Status = MyCustControl.Status.Sixth;
    }

在该注释行上,调试器显示:未将对象引用设置为对象的实例。

请帮忙,我的代码有什么问题?

编辑(添加):

我尝试使用命令方法执行相同的操作:

我使用 RoatedUICommand Requery 声明了一个 DataCommands 类,然后使用 Window.CommandBindings

<Window.CommandBindings>
  <CommandBinding Command="MyNamespace:DataCommands.Requery" Executed="RequeryCommand_Executed"></CommandBinding>
</Window.CommandBindings>

MenuItem 的 XAML 现在看起来像:

<Grid.ContextMenu>
 <ContextMenu>
  <MenuItem  Name="EditStatusCm" Header="Change status"  Command="MyNamespace:DataCommands.Requery"/>
 </ContextMenu>                   
</Grid.ContextMenu>

事件处理程序如下所示:

    private void RequeryCommand_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        IInputElement parent = (IInputElement)LogicalTreeHelper.GetParent((DependencyObject)sender);
        MyCustControl SCurrent = new MyCustControl();
        SCurrent = (MuCustControl)parent;
        string str = SCurrent.Name.ToString();// here I get the same error
        MessageBox.Show(str);
    }

但调试器显示相同的运行时错误:未将对象引用设置为对象的实例。

我的两种方法都缺少什么?

我应该如何在 WPF 上下文菜单项单击事件处理程序中引用右键单击对象?

最佳答案

注意命令参数

<Grid Background="Red" Height="100" Width="100">
    <Grid.ContextMenu>
        <ContextMenu>
            <MenuItem 
                Header="Change status" 
                Click="EditStatusCm_Click"
                CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}" />
        </ContextMenu>
    </Grid.ContextMenu>
</Grid>

并在处理程序中使用它来确定它是哪个网格

    private void EditStatusCm_Click(object sender, RoutedEventArgs e)
    {
        MenuItem mi = sender as MenuItem;
        if (mi != null)
        {
            ContextMenu cm = mi.CommandParameter as ContextMenu;
            if (cm != null)
            {
                Grid g = cm.PlacementTarget as Grid;
                if (g != null)
                {
                    Console.WriteLine(g.Background); // Will print red
                }
            }
        }
    }

更新:
如果您希望菜单项处理程序访问网格的子级而不是网格本身,请使用此方法

<Grid Background="Red" Height="100" Width="100">
    <Grid.Resources>
        <ContextMenu x:Key="TextBlockContextMenu">
            <MenuItem 
                Header="Change status" 
                Click="EditStatusCm_Click"
                CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}" />
        </ContextMenu>

        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="ContextMenu" Value="{StaticResource TextBlockContextMenu}" />
        </Style>
    </Grid.Resources>

    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBlock Text="Row0" Grid.Row="0" />
    <TextBlock Text="Row1" Grid.Row="1" />
</Grid>

只需将 TextBlock 替换为您的自定义对象类型即可。然后在事件处理程序中,替换 Grid g = cm.PlacementTarget as GridTextBlock t = cm.PlacementTarget as TextBlock (或任何您的自定义对象类型)。

关于c# - 如何在 WPF 上下文菜单项单击事件处理程序中引用右键单击对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2032832/

相关文章:

C# WPF 订阅从 UserControl 激发的另一个类中的事件

javascript - 滚动缩放两个图像

c# - 使用 NAudio 在运行时更改波形格式

c# - 安装我的应用程序时如何区分 x86 和 x64 操作系统

wpf - 使用 MVVM 分配数据上下文的最佳方法是什么?

JavaScript "Don´t change states to fast"

objective-c - 如何获取当前事件编号以使用 NSEvent 创建事件

c# - 在使用 ASP.NET Web API 2.0 和身份进行外部登录/注册期间从 Facebook 检索其他个人资料信息

c# - 具有对象类型支持的 .Net 第三方 Oracle 提供程序

c# - 将 ListView 绑定(bind)到具有对象类型的 List<T> 或 List<InterfaceOfT>