解决WPF右键菜单的菜单项左击有效右击无效的问题

解决WPF右键菜单的菜单项左击有效右击无效的问题

最近项目开发过程中遇到了一个问题,自己用ContextMenu创建了右键菜单后,弹出的右键菜单,不管是左击还是右击都是有效的,这显然不符合人们的使用习惯,查了很久的资料,终于解决了这个问题。话不多说,直接上核心部分代码。

public bool IsMouseLeftButtonDown =false;   //判断鼠标是否按下的标志
private static ContextMenu CreatContextMenu_ForNormalButton(uint controlId)
{
    //创建一个右键菜单
    ContextMenu contextMenu = new ContextMenu() { Name = "contextMenu" };
    //将右键菜单进行绑定
    setContextMenu(contextMenu);
    //创建子菜单项
    MenuItem TestItem = new MenuItem() { Name = "MouseLeftButtonDownValid" };
    TestItem.SetResourceReference(MenuItem.HeaderProperty, "Str_MouseLeftButtonDownValid");
    TestItem.CommandParameter = string.Format("{0}:0x{1:X8}", MouseLeftButtonDownValid,controlId);
    TestItem.Command = MyRelayCommand;
    /*注意 这里为子菜单项添加鼠标右键按下事件,一定是PreviewMouseDown,mouseDown不能进入到MenuItem_MouseDown函数,至于为什么要这样,文章后面有说明*/
    TestItem.PreviewMouseDown += new MouseButtonEventHandler(MenuItem_MouseDown);
    //TestItem.MouseDown += new MouseButtonEventHandler(MenuItem_MouseDown);
    //将子菜单项添加到右键菜单中
    contextMenu.Items.Add(TestItem);

    return contextMenu;
}
//绑定右键菜单
private static void setContextMenu(ContextMenu menu)
{
    Binding bind = new Binding();
    bind.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
    bind.Path = new System.Windows.PropertyPath("PlacementTarget");
    menu.SetBinding(ContextMenu.DataContextProperty, bind);
}
//RelayCommand命令
public RelayCommand MyRelayCommand
{
    get
    {
        if (null == this.operateDevice_RelayCommand)
        {
            this.operateDevice_RelayCommand = new RelayCommand(x => this.operateDevice(x), x => this.canOperateDevice(x));
        }
        return this.operateDevice_RelayCommand;
    }
}
//鼠标右键按下的判断函数
private static void MenuItem_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.LeftButton == MouseButtonState.Pressed)
    {
        IsMouseLeftButtonDown = true;   //左键按下有效
    }
    else
    {
        IsMouseLeftButtonDown = false;  //右键按下无效
    }
}

然后通过IsMouseLeftButtonDown这个标志去RelayCommand中的命令执行函数operateDevice中去判断操作是否可以执行,便可以解决这个问题。这里说明PreviewMouseDown与MouseDown的区别:PreviewMouseDown 对应的冒泡事件为 MouseDown 。两者区别是,冒泡关系(或叫触发的先后顺序)。当鼠标按下,先触发PreviewMouseDown,然后,阻止MouseDown的触发(或叫阻止事件传递,或叫停止冒泡),所以可以将PreviewMouseDown视为MouseDown的过滤器(或叫必经之路),通常你可以在PreviewMouseDown中做一些预先处理,为MouseDown做铺垫。或者做一些逻辑判断,以决定是否要触发MouseDown,等等之类,看你的需要而定。
希望对各位正在做C#前端开发的同仁们有用。

参考文献:
1. https://msdn.microsoft.com/zh-cn/library/system.windows.controls.menuitem(v=vs.110).aspx

你可能感兴趣的:(C#编程基础,WPF-右键,contextmenu,鼠标)