【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 ...
随机推荐
- 记一个界面刷新相关的Bug
今天遇到一个比较有意思的bug, 这里简单记录下. Bug的症状是通过拖拉边框把我们客户端主窗口拖小之后,再最大化,会发现窗口显示有问题, 看起来像是刷新问题, 有些地方显示的不对了. 这里要说明的是 ...
- Intellij Idea 2016 配置Tomcat虚拟目录
默认的idea是不需要配置虚拟目录了,它完全托管项目,但是有些时候,在开发过程中,是需要以虚拟目录的形式开发,即以:http://localhost:8080/虚拟目录名/index.html 这种形 ...
- [php入门] 2、基础核心语法大纲
1 前言 最近在学PHP,上节主要总结了PHP开发环境搭建<[php入门] 1.从安装开发环境环境到(庄B)做个炫酷的登陆应用>.本节主要总结PHP的核心基础语法,基本以粗轮廓写,可以算作 ...
- [51单片机] 以从0开始做4位8段共阴数码管3461AS驱动谈细节决定高质量DIY
目录 1)问题产生 2)失败尝试 3)最终方案 4)使用方法 5)知识共享 1)问题产生 在上一篇“以PWM控制直流电机为例建一个简单的51工程框架”中已向大家介绍了一个封装好的8位8段数码管的驱动( ...
- Microsoft Dynamics CRM 2013 and 2011 Update Rollups and Service Packs
Microsoft Dynamics CRM 2013 BTW: RC stands for Release for Candidate, and RTM stands for Release ...
- Java-集合练习题1
第一题 (Map)利用Map,完成下面的功能: 从命令行读入一个字符串,表示一个年份,输出该年的世界杯冠军是哪支球队.如果该 年没有举办世界杯,则输出:没有举办世界杯. 附:世界杯冠军以及对应的夺冠年 ...
- Atitit 如何让精灵控件运动
Atitit 如何让精灵控件运动 ##让Sushi精灵动起来 上面的代码,我们创建了静态的sushiSprite,现在我们让它动起来.使它从屏幕顶部下落到屏幕底部.在addSushi方法中添加如下代 ...
- SSH+JPA查询两个数据库
1.第一步导包: 1.struts2包: 2.spring包: 3.hibernate包: 4.数据库包: 2.web.xml配置 3.struts2的配置: 1.struts.xml 2.s001. ...
- iOS-----Xcode-Debug尝试
在Xcode中,Debug时,不能像eclipse ,或VS那些集成开发那样,能直接查看变量的值.那怎么在调试的时候查看XCode的变量呢? 有一些方法的. 1.新建一个Single View App ...
- hibernate(三) 一对多映射关系
序言 前面两节讲了hibernate的两个配置文件和hello world!.还有hibernate的一级缓存和三种状态,基本上hibernate就懂一点了,从这章起开始一个很重要的知识点,hiber ...