WPF 如何控制右键菜单ContextMenu的弹出
在具体做一些项目的时候,有时候需要需要先左键点击某个节点,然后再右键点击节点的时候才弹出右键菜单,所以直接右键点击时需要禁用掉右键菜单,这里比如我们为Grid添加了ContextMenu,但是我们需要设置一个bool型的变量isSelected,当我们执行到MouseLeftButtonDown事件中的时候,我们就可以将isSelected设置为true,然后在Grid中添加PreviewMouseRightButtonUp="OnMouseRightButtonUp"(隧道事件路由)事件或者是MouseRightButtonUp(冒泡事件路由)事件,在本项目中两者都可以,但是不要添加在<Grid.ContextMenu/>及其子节点下面,这个稍后会介绍,然后在主程序中执行下面的代码:
private void OnMouseRightButtonUp(object sender,MouseButtonEventArgs e)
{
if(isSelected==true)
{
//使消息可以传递
e.Handled=false;
}
else
{
e.Handled=true;
}
isSelected=false;
}
这样当我们先左键点击某一个节点的时候,然后再点击右键的时候才能弹出ContextMenu,这里我们需要正确理解Handled的含义,Handled将路由事件标记为已处理的值。如果 Handled 的值为 true,则可以防止事件路由路径上的大多数处理程序再次处理同一事件。这在实际的事件处理中是非常有用的,因为WPF的这种层层嵌套的UI设计思想,使得某一个事件,例如UIElement.MouseLeftButtonDown在很多元素上都会触发,根据事件的不同类型,可以有冒泡触发或者是隧道的这种方式来触发,但事实上只有一个元素最终执行该事件,如果某一个元素已经执行过该事件,那么它就会将Handled 的值设为 true,这样事件就不会向下或者向上路由了,如果想让事件继续路由就要将Handled设置为false这个是非常重要的,下面的内容参考一下别人写的一篇博客,很有意义。
在读《WPF高级编程》,看到事件的上传和下传。有个例子:
前台代码:
<Window x:Class="TunnelingBubbling.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" >
<Grid MouseLeftButtonDown="Grid_MouseLeftButtonDown"
PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown"
Width="313" Height="271" Name="mygrid">
<Button PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown"
MouseLeftButtonDown="Button_MouseLeftButtonDown" Click="Button_Click" Name="btnGo">
<TextBox Name="textBox1" Width="173" Height="27"
MouseLeftButtonDown="textBox1_MouseLeftButtonDown"
PreviewMouseLeftButtonDown="textBox1_PreviewMouseLeftButtonDown">
</TextBox>
</Button>
</Grid>
</Window>
分别为Grid,Button,TextBox定义了PreviewMouseLeftButtonDown和MouseLeftButtonDown事件,并且为Button定义的Click事件。
后台代码如下:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
} private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Grid_PreviewMouseLeftButtonDown");
} private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Button_PreviewMouseLeftButtonDown");
}
private void textBox1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("textBox1_PreviewMouseLeftButtonDown");
} private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Grid_MouseLeftButtonDown");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Button_Click");
}
private void textBox1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("textBox1_MouseLeftButtonDown");
}
private void Button_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Button_MouseLeftButtonDown");
}
}
但是在执行的时候,MouseLeftButtonDown事件总是无法触发。查看了一些资料,才知道这是一个设计原则上的问题。控件在捕获了MouseLeftButtonDown事件后,会将该事件的“Handled”设置为True,这个属性是用在事件路由中的,当某个控件得到一个RoutedEvent,就会检测Handled是否为true,为true则忽略该事件。
并且,控件本身的Click事件,相当于将MouseLeftButtonDown事件抑制(Supress)掉了,转换成了Click事件。所以,如果一定要使用这个事件的话,需要在初始化的函数里利用UIElement的AddHandler方法,显式的增加这个事件。
---------方法说明:---------------------------------------------------------------------------------
UIElement.AddHandler 方法 (RoutedEvent, Delegate, Boolean)
为指定的路由事件添加路由事件处理程序,并将该处理程序添加到当前元素的处理程序集合中。将 handledEventsToo 指定为 true 时,可为已标记为由其他元素在事件路由过程中处理的路由事件调用所提供的处理程序。
参数说明:
handledEventsToo类型:System..::.Boolean
如果为 true,则将按以下方式注册处理程序:即使路由事件在其事件数据中标记为已处理,也会调用该处理程序;如果为 false,则使用默认条件注册处理程序,即当路由事件被标记为已处理时,将不调用处理程序。
默认值为 false。
修改后的程序代码如下:
public Window1()
{
InitializeComponent();
mygrid.AddHandler(Grid.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.Grid_MouseLeftButtonDown), true);
btnGo.AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.Button_MouseLeftButtonDown), true);
textBox1.AddHandler(TextBox.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.textBox1_MouseLeftButtonDown), true);
}
再次运行,调用成功,事件的执行顺序是:
|
次序 |
控件 |
事件 |
事件类型 |
|
1 |
Grid | PreviewMouseLeftButtonDown |
下传 |
|
2 |
Button | PreviewMouseLeftButtonDown |
下传 |
|
3 |
TextBox | PreviewMouseLeftButtonDown |
下传 |
|
4 |
TextBox | MouseLeftButtonDown |
上传 |
|
5 |
Button | MouseLeftButtonDown |
上传 |
|
6 |
Grid | MouseLeftButtonDown |
上传 |
如果点击Button,则事件的执行顺序是:
|
次序 |
控件 |
事件 |
事件类型 |
|
1 |
Grid | PreviewMouseLeftButtonDown |
下传 |
|
2 |
Button | PreviewMouseLeftButtonDown |
下传 |
|
3 |
Button | MouseLeftButtonDown |
上传 |
|
4 |
Grid | MouseLeftButtonDown |
上传 |
|
5 |
Button | Click |
最后补充一点:
在事件处理程序中,可以取消事件处理,查找事件的源元素
例如在下面的代码中:
private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Button_PreviewMouseLeftButtonDown");
// e.Handled = true;
// Button myButton = e.Source as Button;
}
1.取消事件处理: 设置 e.Handled = true;
2.在事件处理程序中查找源元素: e.Source 传递一个实际对象实例,可以将其强制转换为System.Windows.Controls.Button类型,通过这个变量,可以访问这个控件提供的所有本地属性,方法和事件。
WPF 如何控制右键菜单ContextMenu的弹出的更多相关文章
- 【WPF】右键菜单ContextMenu可点击区域太小的问题
问题描述 正常使用右键菜单ContextMenu时,如果菜单项是不变的,可以直接在XAML中写死,如下是给一个Button按钮添加了右键菜单功能. <Button Content="T ...
- wpf datagrid设置右键菜单打开时选中项的背景色
原文:wpf datagrid设置右键菜单打开时选中项的背景色 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/huangli321456/artic ...
- jQuery右键菜单contextMenu实例
URL: http://www.cnblogs.com/whitewolf/archive/2011/09/28/2194795.html http://www.blogjava.net/superc ...
- ExtJS配置TabPanel的鼠标右键菜单(ContextMenu)功能
更新记录 2022年6月14日 发布. 2022年6月13日 初稿. TabPanel的鼠标右键菜单(ContextMenu)功能介绍 开源的TabPanel组件很少做到拖拽调整tab顺序功能的,支持 ...
- web标准(复习)--4 纵向导航菜单及二级弹出菜单
今天我们开始学习纵向导航菜单及二级弹出菜单,包含以下内容和知识点: 纵向列表 标签的默认样式 css派生选择器 css选择器的分组 纵向二级列表 相对定位和绝对定位 一.纵向列表纵向列表或称为纵向导航 ...
- Web标准:四、纵向导航菜单及二级弹出菜单
Web标准:四.纵向导航菜单及二级弹出菜单 知识点: 1.纵向列表 2.标签的默认样式 3.css派生选择器 4.css选择器的分组 5.纵向二级列表 6.相对定位和绝对定位 1)纵向列表 可以看 ...
- jQuery右键菜单contextMenu使用实例
在最近项目中需要频繁的右键菜单操作.我采用了contextMenu这款jQuery插件. 参考网址:http://www.jb51.net/article/58709.htm 官网demo http: ...
- Jquery 右键菜单(ContextMenu)插件使用记录
目前做的项目需要在页面里面用右键菜单,在网上找到两种jquery的右键菜单插件,但是都有各种问题.所以就自己动手把两种插件结合了下. 修改后的右键菜单插架可以根据绑定的触发页面元素不同,复用同一个菜单 ...
- 鼠标右键Table的td弹出多级菜单,双击td编辑
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
随机推荐
- mysql中engine=innodb和engine=myisam的区别(转)
转自http://blog.csdn.net/lingyi_xu/article/details/5393791 innodb引擎和mysiam引擎的区别 引擎 事务 外键 建 ...
- 1605--luogu(深搜dfs)
据说 这是一道很水的题 emmm 好吧 是我过分水了 ------------------------------------------------------------------------ ...
- Qt+Qgis二次开发:在状态条显示当前鼠标坐标
1 概述 鼠标在地图上移动,需要实时获取当前坐标位置.2 原理 从当前位置获取视口坐标后,实时转换为地图坐标.3 方法 处理鼠标位置,必须获取鼠标的当前坐标.但是Qt的鼠标事件由QgsMapCanv ...
- [转]Win7 + Ubuntu 18.04 LTS (Bionic Beaver)双系统安装方法
这里介绍在win7的基础上,安装ubuntu 18.04 LTS,实现双系统启动. 首先,假设你已安装了windows 7系统. 一. 制作ubuntu U盘启动盘. 方法见http://blog.p ...
- JVM解释器和编译器
首先看一个命令 [root@insure ~]# java -version java version "1.8.0_191" Java(TM) SE Runtime Enviro ...
- Centos 7 KVM安装win10
KVM架构: KVM 是基于虚拟化扩展(Intel VT 或者 AMD-V)的 X86 硬件的开源的 Linux 原生的全虚拟化解决方案.KVM 中,虚拟机被实现为常规的 Linux 进程,由标准 L ...
- IDEA Maven Jetty Jrebel 热部署
准备:1.下载Jrebel的离线安装包,版本是6.4.3版本. 2.下载Jrebel的破解补丁包,同样也是针对6.4.3版本的 Jrebel离线安装包官网下载地址:https:/ ...
- VS2013开发上位机并调用MSCcommm控件的方式
此文章适合VC++串口通信入门 一.页面布局及添加控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目comm 注意:点击ok,然后next,这时候要将application t ...
- 苹果与Windows双系统时间不同步的解决办法
步骤:打开C盘>Windows>System32,找到cmd.exe,右键以管理员的身份运行. Reg add HKLM\SYSTEM\CurrentControlSet\Control\ ...
- ES6-课程介绍
ES6 可以提高开发效率,把ES3比做斧头,ES5比做锯子,那么ES6就是电锯. ES6新特性 默认参数.字符串模板.结构赋值.箭头函数.set\mat .异步操作.类和对象 .模块化