如何删除事件处理程序并将其重新附加到 c# 中的控件?
Posted
技术标签:
【中文标题】如何删除事件处理程序并将其重新附加到 c# 中的控件?【英文标题】:How to remove and re-attatch EventHandler to controls in c#? 【发布时间】:2013-04-21 23:36:54 【问题描述】:我读过这个answer。
它只是告诉我如何从按钮控件中删除单击事件。我想知道如何更改代码(尤其是GetField("EventClick"...
部分!),这样我就可以对其他控件做同样的事情。例如,我想删除TextBox
的TextChanged
事件。
而且我还想知道如何重新附加事件处理程序。
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void textBox1_TextChanged(object sender, EventArgs e)
if (textBox1.Text.Length < 10) return;
MessageBox.Show("do something");
private void Form1_Load(object sender, EventArgs e)
Tools.mkTextBoxWithPlaceholder(textBox1, "hi, input here...");
class Tools
public static void mkTextBoxWithPlaceholder(TextBox tb, string placeholder)
tb.Tag = placeholder;
tb.GotFocus += new EventHandler(tb_GotFocus);
tb.LostFocus += new EventHandler(tb_LostFocus);
private static void tb_GotFocus(object sender, EventArgs e)
TextBox tb = sender as TextBox;
tb.Clear();
private static void tb_LostFocus(object sender, EventArgs e)
TextBox tb = sender as TextBox;
//TODO Remove the TextChanged event handler here.
tb.Text = tb.Tag as string;
//TODO Reattach the TextChanged event handler here.
使用上面的代码,textBox1 将具有类似于占位符的功能。也许您可以就如何将占位符添加到文本框给我一些帮助。这就是我想要的。
【问题讨论】:
哦!现在我看到了你想要达到的目标! 【参考方案1】:删除
Mybutton.event -= methodname;
重新连接
Mybutton.event += methodname;
【讨论】:
【参考方案2】:根据this post of mine,这是您的问题的解决方案。
这些帮助方法让您可以操作特定控件的任何事件:
// Also searches up the inheritance hierarchy
private static FieldInfo GetStaticNonPublicFieldInfo(Type type, string name)
FieldInfo fi;
do
fi = type.GetField(name, BindingFlags.Static | BindingFlags.NonPublic);
type = type.BaseType;
while (fi == null && type != null);
return fi;
private static object GetControlEventKey(Control c, string eventName)
Type type = c.GetType();
FieldInfo eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName);
if (eventKeyField == null)
if (eventName.EndsWith("Changed"))
eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName.Remove(eventName.Length - 7)); // remove "Changed"
else
eventKeyField = GetStaticNonPublicFieldInfo(type, "EVENT_" + eventName.ToUpper());
if (eventKeyField == null)
// Not all events in the WinForms controls use this pattern.
// Other methods can be used to search for the event handlers if required.
return null;
return eventKeyField.GetValue(c);
private static EventHandlerList GetControlEventHandlerList(Control c)
Type type = c.GetType();
PropertyInfo pi = type.GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
return (EventHandlerList)pi.GetValue(c, null);
然后您可以使用它们来临时分离事件处理程序:
private static void tb_LostFocus(object sender, EventArgs e)
TextBox tb = (TextBox)sender;
var eventList = GetControlEventHandlerList(tb);
var eventKey = GetControlEventKey(tb, "TextChanged");
// Remove the handlers
var handlers = eventList[eventKey];
eventList.RemoveHandler(eventKey, handlers);
// ... perform your task
// Reattach the handlers
eventList.AddHandler(eventKey, handlers);
如果您想知道这里到底发生了什么,请继续阅读。
Windows 窗体使用EventHandlerList
类来维护控制事件。使用对象类型的简单键访问每个事件。密钥存储在控件的私有字段中。访问此数据的唯一方法是使用反射,但我们应该知道事件键字段的名称。通过反编译Control
类及其后代,我们可以看到键使用不同的名称。我在键中提取了三种常见的命名模式,并在GetControlEventKey
方法中使用它们。
这是 WinForms 控件用来保存事件处理程序的机制。它没有什么特别之处。这只是一种设计选择。
【讨论】:
我试过你的代码,但 eventKeyField 总是为空。字符串“EventTextChanged”和“EVENT_TextChanged”用于搜索事件处理程序,不是吗?你能给我一些可以完成这项工作的代码吗?我会编辑我的问题,所以你会清楚地看到问题。 是的,它很好用!但是我怎样才能写出正确的搜索字符串?你使用了“EventText”,它成功了。你能告诉我为什么吗?以上是关于如何删除事件处理程序并将其重新附加到 c# 中的控件?的主要内容,如果未能解决你的问题,请参考以下文章
在 DOM 中的所有元素上附加 click 事件的事件处理程序