我需要从从我没有代码的 dll 加载的控件中删除事件处理程序。由于似乎没有“官方”(即由 .NET Framework 的公共方法支持),因此我能够创建几个扩展方法,这些方法正是使用 Reflection 来完成此操作。
有关所有详细信息,请参阅此博客文章:使用反射从 WinForm ListView 控件中删除事件
这里是如何删除 SelectedIndexChanged 事件的代码示例(动态且无需访问原始处理程序)
//for a UserControl (in fact any control that implements System.ComponentModel.Component)
var userControl = new UserControl();
//we can get the current mapped event handlers
userControl.eventHandlers();
//its signature
userControl.eventHandlers_MethodSignatures();
//remove one by using the static field name
userControl.remove_EventHandler("EVENT_SELECTEDINDEXCHANGED");
//or use this one specifically mapped to the SelectedIndexChanged event
userControl.remove_Event_SelectedIndexChanged
我的问题是:“还有其他方法吗?”
虽然我的解决方案有效并且看起来稳定,但我正在进行内部 .NET 对象操作,所以也许有更好的解决方案(在 4.0 或 4.5 中)?
相关帖子:
可以使用以下代码从控制器中删除事件,它是一种扩展方法:
public static void EventHandlersClear(this Control control, params string[] eventKeyNames)
{
if (eventKeyNames == null) return;
if (eventKeyNames.Length == 0) return;
var allEventFields = typeof(Control).GetFields(BindingFlags.Static | BindingFlags.NonPublic);
var eventFields = allEventFields.Where(q => eventKeyNames.Contains(q.Name)).ToList();
if (eventFields.Count == 0) return;
var eventsProperty = control.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
var events = (EventHandlerList)eventsProperty.GetValue(control, null);
foreach (var eventKey in eventFields)
{
events.RemoveHandler(eventKey, events[eventKey]);
}
}
例如使用 .net Framework 4.8 创建一个 Windows 应用程序:
代码后面:
private void ClearEventHandlersBTN_Click(object sender, EventArgs e)
{
button1.EventHandlersClear("EventClick", "EventMouseDown", "EventMouseClick");
button2.EventHandlersClear("EventClick", "EventMouseDown", "EventMouseClick");
button3.EventHandlersClear("EventClick", "EventMouseDown", "EventMouseClick");
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("button1_Click");
}
private void button3_Click(object sender, EventArgs e)
{
MessageBox.Show("button3_Click");
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("button2_Click");
}
private void button1_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("button1_MouseClick");
}
private void button2_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("button2_MouseClick");
}
private void button3_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("button3_MouseClick");
}
private void button3_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show("button3_MouseDown");
}
private void button2_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show("button3_MouseDown");
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show("button3_MouseDown");
}
要使用此扩展方法,您需要知道控件类型中事件字段的名称。
可以使用以下代码来获取所有事件字段名称:
typeof(Control).GetFields(BindingFlags.Static | BindingFlags.NonPublic)