遗忘海岸

江湖程序员 -Feiph(LM战士)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

匿名委托注册事件的触发

需求
需要在DataGridView新增行时触发新行第二列的双击事件以显示数据选择窗体,具体如下图

事件代码入下
 //单元格双击事件处理  

复制代码
View Code
            dataGridView1.CellDoubleClick +=  (s, e) =>
            {
                if (e.RowIndex < 0) return;
                var curItem=bindingSource1.Current as KB_Route;
               
                if (e.ColumnIndex >= 0 && dataGridView1.Columns[e.ColumnIndex].Name == "workStationIdColumn")
                {
                    var frm = new frmWorkStationSelector();
                    frm.StartPosition = FormStartPosition.CenterParent;
                    if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        var refEnt = frm.RefEntity;
                        if (curItem != null)
                        {
                            curItem.WorkStationId = refEnt.WorkStationId;
                            curItem.WSName = refEnt.WSName;
                            bindingSource1.EndEdit();
                        }
                    }
                    frm.Dispose();
                }
            };
复制代码

 办法一

在窗体定义个字段,定义匿名委托时顺便设置该字段,在添加新行时直接调用就完事.
在匿名委托出现之前上面的问题根本就不是问题,不过既然匿名委托可以将事件处理代码写的紧凑点,那么办法1就显的不完美.


办法二
通过反射,控件的CellDoubleClick事件是通过事件属性方式声明的,借助Reflector可以看到相关的字段定义,实现的调用代码如下

复制代码
View Code
                //反射方式调用
                var ptyInfo = dataGridView1.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
                if (ptyInfo != null)
                {
                    var handleList = ptyInfo.GetValue(dataGridView1, null) as EventHandlerList;
                    var fieldInfo = dataGridView1.GetType().GetField("EVENT_DATAGRIDVIEWCELLDOUBLECLICK", BindingFlags.Static | BindingFlags.NonPublic);

                    var d = handleList[fieldInfo.GetValue(dataGridView1)];
                    if (d != null)
                    {
                        d.DynamicInvoke(dataGridView1, new DataGridViewCellEventArgs(columnIndex, rowIndex));
                    }
                }
复制代码

该方法需要通过反射方式获取EventHandlerList与注册用的key,不过由于Key声明的是private的,所以很难保证MS啥时候就把变量名称改了,总不能每次换版本时都用Reflector查看下把(貌似从.net2.0到4.0该字段名没变过)


办法三
MS控件的事件一般都有一个protected OnXXX签名字样的方法来调用事件处理程序,那么直接反射调用它就完事了,而且由于是protected的比起private要靠谱点.

View Code
                var dg = dataGridView1.GetType().GetMethod("OnCellDoubleClick",BindingFlags.NonPublic | BindingFlags.Instance);
                dg.Invoke(dataGridView1,new object[]{ new DataGridViewCellEventArgs(columnIndex, rowIndex)});

 



posted on   遗忘海岸  阅读(1498)  评论(3编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
历史上的今天:
2008-09-04 T-SQL 选择某一记录的前后相关记录
点击右上角即可分享
微信分享提示