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