DevExpress SpreadsheetControl 反射移除事件委托

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;
        }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值