我需要从从我没有代码的 dll 加载的控件中删除事件处理程序。由于似乎没有“官方”(即受 .NET Framework 的公共方法支持),因此我能够创建几个扩展方法,这些方法正是使用反射来完成此操作。
有关所有详细信息,请参阅此博客文章:使用反射从 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
Run Code Online (Sandbox Code Playgroud)
我的问题是:“还有其他方法吗?”
虽然我的解决方案有效并且看起来稳定,但我正在进行内部 .NET 对象操作,所以也许有更好的解决方案(在 4.0 或 4.5 中)?
相关文章:
小智 0
可以使用以下代码从控制器中删除事件,它是一种扩展方法:
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]);
}
}
Run Code Online (Sandbox Code Playgroud)
例如使用 .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");
}
Run Code Online (Sandbox Code Playgroud)
要使用此扩展方法,您需要知道控件类型中事件字段的名称。
可以使用以下代码获取所有事件字段名称:
typeof(Control).GetFields(BindingFlags.Static | BindingFlags.NonPublic)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2129 次 |
| 最近记录: |