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 ...
随机推荐
- WebService之nginx+(php-fpm)结构模型剖析及优化
随着php脚本语言使用的普及,目前webserice服务大部分都在用nginx+(php-fpm)的结构,了解了其工作过程后才可以在各个方面想办法做调整优化和故障排查,从以下几点总结一下这种模型. 一 ...
- 文件上传之Servlet
导包 commons-fileupload-1.3.1.jar commons-io-2.2.jar import java.io.File; import java.io.FileOutputStr ...
- vue之路由嵌套,子路由
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- LNMP安装201812012237
发表这篇文章最初的意愿是想做个最新版的zabbix使用,后来看了下好多“软件”都升级了(如nginx.mysql等),就想干脆做个最新版本的LNMP环境得了,再单独做zabbix的最新版本省得以后升级 ...
- git使用备注
git clone 代码库地址 git branch -r 查看远程分支 git branch 查看本地分支 git branch -a 查看远程和本地分支.带*的表示正在所处分支. git bra ...
- java读取写入文件
先来看一下java写入文件 public static void readTxt(String value) throws IOException { FileWriter fw = null; tr ...
- Spring Extensible XML
Spring框架从2.0版本开始,提供了基于Schema风格的Spring XML格式用来定义bean的扩展机制.引入Schema-based XML是为了对Traditional的XML配置形式进行 ...
- Luogu4652 CEOI2017 One-Way Streets 树上差分
传送门 题意:给出$N$个点.$M$条无向边的图,现在你需要给它定向,并满足$Q$个条件:每个条件形如$(x_i,y_i)$,表示定向之后需要存在路径从$x_i$走向$y_i$.问每条边是否都有唯一定 ...
- flask-script&flask-migrate使用
一.简介 Flask-script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell.设置数据库的脚本.cronjobs及其他运行在web应用之外的 ...
- C# webApi上传图片 代码篇
十年河东,十年河西,莫欺少年穷 学无止境,精益求精 代码篇,不多说 如下: using System; using System.Collections.Generic; using System.D ...