DevExpress SpreadsheetControl 反射移除事件委托

原创 2016年08月30日 14:17:51

c#中,在没有已绑定的事件委托实例的情况下,移除事件委托。

目前涉及要移除事件包含:CellEndEdit/MouseClick/CellValueChanged/ProtectionWarning/ScrollPositionChanged/SelectionChanged

参照原理代码如下:

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button12_Click(object sender, EventArgs e)
        {
            // 为按钮添加两个事件
            this.button13.Click += new EventHandler(button12_Click_1);
            this.button13.Click += new EventHandler(button12_Click_2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button12_Click_1(object sender, EventArgs e)
        {
            MessageBox.Show("1");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button12_Click_2(object sender, EventArgs e)
        {
            MessageBox.Show("2");
        }        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button14_Click(object sender, EventArgs e)
        {
            // 检索按钮的事件,这里单击事件的名字是EventClick,要注意的
            Delegate[] invokeList = GetObjectEventList(this.button13, "EventClick");
            if (invokeList != null)
            {
                foreach (Delegate del in invokeList)
                {
                    typeof(Button).GetEvent("Click").RemoveEventHandler(this.button13, del);
                }
            }
        }        

        /// <summary>
        /// 获取控件事件  
        /// </summary>
        /// <param name="p_Control">对象</param>
        /// <param name="p_EventName">事件名 EventClick EventDoubleClick </param>
        /// <returns>委托列</returns>
        public Delegate[] GetObjectEventList(Control p_Control, string p_EventName)
        {
            PropertyInfo _PropertyInfo = p_Control.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
            if (_PropertyInfo != null)
            {
                object _EventList = _PropertyInfo.GetValue(p_Control, null);
                if (_EventList != null && _EventList is EventHandlerList)
                {
                    EventHandlerList _List = (EventHandlerList)_EventList;
                    FieldInfo _FieldInfo = (typeof(Control)).GetField(p_EventName, BindingFlags.Static | BindingFlags.NonPublic);
                    if (_FieldInfo == null) return null;
                    Delegate _ObjectDelegate = _List[_FieldInfo.GetValue(p_Control)];
                    if (_ObjectDelegate == null) return null;
                    return _ObjectDelegate.GetInvocationList();
                }
            }
            return null;
        }

但是在DevExpress的SpreadsheetControl控件中,通过下面代码
(typeof(DevExpress.XtraSpreadsheet.SpreadsheetControl)).GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance)
找不到上面的事件。通过与客服沟通,原来onCellBeginEdit藏在spreadsheetcontrol的InnerControl属性中,其它几个事件也是在不同属性中。

写了一段代码用于查询事件在哪个属性中,然后再基于上面的原理代码就可以实现在不知道委托实例的情况下移除某事件委托。

            StringBuilder sb = new StringBuilder();
            PropertyInfo[] propertyInfos = spreadsheetControl1.GetType().GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
            List<string> eventNames = new List<string>()
            {
                "onCellBeginEdit",
                "onCellEndEdit",
                "onCellValueChanged",
                "onProtectionWarning",
                "onScrollPositionChanged",
                "onSelectionChanged"
            };
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                object obj = propertyInfo.GetValue(spreadsheetControl1, null);
                if (obj == null) continue;
                foreach (string eventName in eventNames)
                {                    
                    FieldInfo fieldInfo = obj.GetType().GetField(eventName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
                    if (fieldInfo != null)
                        sb.AppendLine(string.Format("事件名称:{0},属性名称:{1}", eventName, propertyInfo.Name));
                }
            }
            memoEdit1.Text = sb.ToString();

附几个事件对应PropertyInfo名称

            Dictionary<string, string> events = new Dictionary<string, string>()
            {
                {"onCellBeginEdit","InnerControl"},
                {"onCellEndEdit","InnerControl"},
                {"onCellValueChanged","InnerControl"},
                {"onProtectionWarning","InnerControl"},
                {"onScrollPositionChanged","DocumentModel"},
                {"onSelectionChanged","DocumentModel"}
            };

改写的GetObjectEventList函数代码

        /// <summary>
        /// 获取SpreadsheetControl中某事件已绑定的委托列表
        /// </summary>
        /// <param name="spreadsheetControl"></param>
        /// <param name="propertyName">拥有该事件的属性名称</param>
        /// <param name="eventName">事件名称,一般前缀on</param>
        /// <returns></returns>
        public Delegate[] GetObjectEventList(DevExpress.XtraSpreadsheet.SpreadsheetControl spreadsheetControl, string propertyName, string eventName)
        {
            PropertyInfo propInfo = spreadsheetControl.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic);
            if (propInfo == null) return null;

            object obj = propInfo.GetValue(spreadsheetControl, null);
            if (obj == null) return null;

            FieldInfo fieldInfo = obj.GetType().GetField(eventName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance);
            if (fieldInfo == null) return null;

            Delegate fieldValue = (Delegate)fieldInfo.GetValue(obj);
            if (fieldValue == null) return null;

            Delegate[] delegates = fieldValue.GetInvocationList();
            return delegates;
        }


相关文章推荐

DevExpress SpreadsheetControl 经验小记

这一段用spreadsheetcontrol,好多问题,记性越来越差,记录一下
  • jjhua
  • jjhua
  • 2014年08月02日 10:38
  • 11214

DevExpress SpreadsheetControl 分组

实现效果:点击单元格,该单元格下方临近的分组收缩或展开。由于DevExpress SpreadsheetControl控件本身的Bug,被点击的单元格上方不能紧邻另外一个分组,否则也会被展开。 原理...
  • jjhua
  • jjhua
  • 2015年10月11日 21:09
  • 1605

DevExpress自定义Spreadsheetcontrol 单元格右键菜单

using DevExpress.XtraSpreadsheet; using DevExpress.XtraSpreadsheet.Commands; using DevExpress.XtraSp...
  • jjhua
  • jjhua
  • 2015年06月18日 22:31
  • 2002

Winform之SpreadSheetGear转DevExpress.XtraSpreadsheet.v13.2实践

DevExpress.XtraSpreadsheet.v13.2 允许用户创建、管理、打印、转换spreadsheet文件而不需要用户安装Office。 什么是Spreadsheet 可以看到最后就...

DevExpress 13.2.6的一些变化

CodeRush for Visual Studio .NET DevExpress.CodeRush.UserControls.EmphasisCallback - 委托的参数列表已经发生了变...

使用DevExpress官方汉化文

使用DevExpress官方汉化文件对界面进行汉化的过程 在较早期的Dev开发中,基本上都是在使用一个DLL包的汉化文件,如基于13.1的汉化包文件Dxper.LocalizationCHS.Win...

DevExpress SpreasheetControl 单元格拖拽

DevExpress SpreasheetControl 单元格拖拽
  • jjhua
  • jjhua
  • 2015年06月27日 09:56
  • 985

Devexpress Spreadsheet 中文教程(3)

导入和导出数据 如何导入数据到Worksheet Import Data from Arrays Worksheet worksheet = workbook.Worksheets[0]; // Cr...
  • hotmee
  • hotmee
  • 2016年01月21日 15:05
  • 1984

Devexpress Spreadsheet 中文教程(1)

如何使用Workbook打开文档 1、从文件打开: workbook.LoadDocument("Documents\\Document.xlsx", DocumentFormat.OpenXml);...
  • hotmee
  • hotmee
  • 2016年01月21日 12:35
  • 4022

jQuery unbind 删除绑定事件 / 移除标签方法

jQuery unbind 删除绑定事件 unbind([type],[data]) 是 bind()的反向操作,从每一个匹配的元素中删除绑定的事件。如果没有参 数,则删除所有绑定的事件...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DevExpress SpreadsheetControl 反射移除事件委托
举报原因:
原因补充:

(最多只允许输入30个字)