【C#】让工具栏ToolStrip能触发焦点控件的Leave、Validating、DataError等事件以验证数据
----------------更新:2014-04-21---------------
蒙doggo兄指教,得知有更好的方法可以代替蹩脚的0尺寸Button法,即调用窗体的验证方法Form.Validate(),该方会触发窗体中焦点控件的Validating事件以验证数据,达到与0尺寸Button法几乎相同的效果。先看采用新方法的代码:
public class ToolStripEx : ToolStrip
{
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
Form fm = FindForm();
if (fm != null) { fm.Validate(); }
}
}
之所以说几乎,是因为还是有一点不同,就是Form.Validate()并不会触发焦点控件的Leave事件,所以需要该事件的猿友恐怕还得继续沿用0尺寸Button法或另想他法。
另外发现ToolStrip还有个操蛋的问题,就是上述方法都只对ToolStripButton的Click事件有效,但如果按钮是分离按钮ToolStripSplitButton,大家知道,按钮部分的单击事件就该用ButtonClick而不是Click,单击按钮部分虽然也会先触发ToolStrip.Click事件进行验证,但不管验证结果如何,ButtonClick都会被执行,不像ToolStripButton.Click那样,验证不过就不会执行。所以对付ButtonClick,在找到更好的办法前,我还得在事件处理方法中加判断才行。真他娘的让人不省心。
----------------原文:2014-03-24---------------
如题,Winform码农大概都知道这样一个问题,就是当输入焦点仍处在TextBox、DataGridViewCell等控件中时,如果单击普通Button、CheckBox等控件,那么该验证的会得到验证,该提交的会提交,该报错的会报错,该被阻止的操作会被阻止。但如果单击的是工具栏上的项目(如ToolStripButton,之所以说项目而不是控件,你懂的),是不会触发焦点控件的验证事件的,而是会直接执行按钮事件,这样带来的影响相信大家深有体会。总之不解决ToolStrip的这个问题我不会幸福。先看办法:
/// <summary>
/// 工具栏(无右侧竖线、无手柄、可触发其它控件验证)
/// </summary>
public class ToolStripEx : ToolStrip
{
readonly Button btn;//定义一个用来转移焦点的控件,如Button public ToolStripEx()
{
//初始化并指定控件尺寸为0,0。因为你不会希望这个按钮被看到
btn = new Button { Width = , Height = }; //下面为可选项
//让工具栏在视觉上更地道。如被按下的ToolStripButton更明显,否则只有一个惨淡的线框
ToolStripManager.VisualStylesEnabled = false; //不显示拖曳抓柄
GripStyle = ToolStripGripStyle.Hidden;
} //在工具栏获得句柄后将控件添加进窗体,之所以不在构造函数中做这事是因为那个时候窗体也许还是null
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
Form fm = this.FindForm();
if (fm != null) { fm.Controls.Add(btn); }//这样添加后,btn.Location会是0,0
} //在工具栏被碰到时(其实选用其它类似事件也行)将焦点转移到btn上,以此触发焦点控件的验证
//注意虽然是工具栏的Click,但经过实践点击其中的子项都会优先触发该事件
//所以当焦点控件验证通不过时,不会再执行子项的Click事件,这一点我想是由win32消息机制实现的
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
btn.Focus();
} //可选。把工具栏最右边的1px竖线K掉,这种瑕疵对于我来说简直不能忍受,草泥马微软,有病
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SetClip(new Rectangle(, , Width - , Height));
base.OnPaint(e);
}
}
办法很简单,就是在点击工具栏时先把焦点移到其它能正常获得焦点的控件上,以此来触发先前控件的Leave/Validating/DataError等事件。
其实为了解决这个问题我颇费了一番周折,最开始想到的其实就是这招,但觉得猥琐了点,作为一个有追求的码农,我认为应该从消息层面去解决,所以一开始就把这个阴招放在一边,专心捣鼓消息。开始我认为这个问题的本质是因为,工具栏就像Panel之类的控件,是得不到焦点的控件,不像Button之流,能够让其他控件的焦点转移过来,所以才有这个问题。那么我就想通过调用win32 API,让工具栏能发出与Button一样的消息,让焦点控件受骗,以为点到的是Button,从而验证自己的数据,移交自己的焦点。经过多番实践,确实让工具栏获得了焦点,让焦点控件失去焦点,用Spy++看焦点控件接收到的消息也与点击Button接收到的消息看起来一样了,但仍然不会触发验证,这就扯蛋了~我那个沮丧啊。BTW~其实给工具栏设置SetStyle(ControlStyles.Selectable, true)也可以达到同样目的,但一样解决不了问题。
也许是还没摸透问题的本质,也许是win32消息还是玩不转~总之是经历过若干次失败的尝试,我不得不放弃高大上的解决办法,这才回头来重新拾起猥琐方案,所以文中办法其实是妥协的结果,难免心有不甘,等他日机缘到了,我定再次尝试“正统”的解决办法。如有路过高人点拨,感激不尽!
【C#】让工具栏ToolStrip能触发焦点控件的Leave、Validating、DataError等事件以验证数据的更多相关文章
- 工具栏ToolStrip能触发焦点控件的Leave、Validating、DataError等事件以验证数据 z
public class ToolStripEx : ToolStrip { protected override void OnClick(EventArgs e) { base.OnClick(e ...
- 在asp.net页面上按回车会触发Imagebutton控件的Click事件
原文:在asp.net页面上按回车会触发Imagebutton控件的Click事件 问题: 用asp.net做的aspx页面,无论是否有文本框.下拉框.复选框……获得焦点,只要在当前页面上按一下回车就 ...
- JQuery 点击子控件事件,不会触发父控件的事件
$('.order-delete').on('tap', function (e) { console.log('删除1'); c ...
- VC++ 如何在显示对话框的时候,指定焦点控件!
很简单: 在你的CAddDlg类的OnInitDialog函数中加上你上面的代码GetDlgItem(IDC_EDIT1)->SetFocus();最后记得return FALSE; 其实,不知 ...
- asp.net无法触发asp控件的后台方法
前台代码: <asp:Button ID="btnFinish" runat="server" Text="完成" Font-Size ...
- c#中如何保存焦点控件?
对所有文本框添加焦点获得事件,头部再定义一个全局的object或者control的类型对象,在焦点获得事件中把当前控件对象赋值给之前定义的object或者control对象,操作的话就对这个全局量操作 ...
- 关于Asp.net事件,如何在触发子控件的事件时,同步触发父页面的事件
对页面引用自定义控件后,通过绑定自定义事件,页面绑定子控件的事件,在子控件做了某些修改动作后,如何同步操作父页面的方法:下面我煮了个栗子,同学们可以来尝一尝试一试 a.aspx 引用 UserCont ...
- VS2012或VS2010 工具栏中无法显示DevExpress控件
进入命令提示符 跳转到Dev控件安装目录,如[目录D:\Program Files (x86)\DevExpress\DXperience 12.2\Tools]下, 然后执行命令: ToolboxC ...
- SDI在自定义的工具栏上添加下拉控件
0.首先到自己的工具条上新建一个控件,并命名新ID 1.拷贝FlatComboBox.h和FlatComboBox.cpp到工程目录下 2.建立新类 class CTrackerToolBar : p ...
随机推荐
- [ZigBee] 12、ZigBee之看门狗定时器——饿了就咬人的GOOD DOG
引言:硬件中的看门狗,不是门卫的意思,而是一只很凶的狗!如果你不按时喂它,它就会让系统重启!这反而是我们想要的功能~ 1.看门狗概述 看门狗定时器(WDT,Watch Dog Timer)是单片机的一 ...
- XSS危害——session劫持
在跨站脚本攻击XSS中简单介绍了XSS的原理及一个利用XSS盗取存在cookie中用户名和密码的小例子,有些同学看了后会说这有什么大不了的,哪里有人会明文往cookie里存用户名和密码.今天我们就介绍 ...
- 跟我一起云计算(1)——storm
概述 最近要做一个实时分析的项目,所以需要深入一下storm. 为什么storm 综合下来,有以下几点: 1. 生逢其时 MapReduce 计算模型打开了分布式计算的另一扇大门,极大的降低了实现分布 ...
- 案例研究:CopyToAsync
返回该系列目录<基于Task的异步模式--全面介绍> 把一个流拷贝到另一个流是有用且常见的操作.Stream.CopyTo 方法在.Net 4中就已经加入来满足要求这个功能的场景,例如在一 ...
- IOS Socket 01-网络协议基础知识
1. 网络参考模型 OSI参考模型 TCP/IP参考模型 2. 七层简述 1)物理层:主要定义物理设备标准,如网线的接 ...
- IOS Runtime-初识runtime(一)
苹果公布了runtime的源码,可以从地址下载:http://www.opensource.apple.com/tarballs/objc4/ object-c程序在启动的时候,需要一个准备时间,这个 ...
- Node.js与Sails~方法拦截器policies
回到目录 policies sails的方法拦截器类似于.net mvc里的Filter,即它可以作用在controller的action上,在服务器响应指定action之前,对这个action进行拦 ...
- WebApi系列~通过HttpClient来调用Web Api接口~续~实体参数的传递
回到目录 上一讲中介绍了使用HttpClient如何去调用一个标准的Web Api接口,并且我们知道了Post,Put方法只能有一个FromBody参数,再有多个参数时,上讲提到,需要将它封装成一个对 ...
- 纯js实现复制到剪贴板功能
在网页上复制文本到剪切板,一般是使用JS+Flash结合的方法,网上有很多相关文章介绍.随着 HTML5 技术的发展,Flash 已经在很多场合不适用了,甚至被屏蔽.本文介绍的一款JS插件,实现了纯J ...
- @SuppressWarnings忽略警告
简介:java.lang.SuppressWarnings是J2SE 5.0中标准的Annotation之一.可以标注在类.字段.方法.参数.构造方法,以及局部变量上.作用:告诉编译器忽略指定的警告, ...