How to remove and reinstall EventHandler on controls in C #?

I read this answer . Just tell me how to remove a click event using the control button. I want to know how to change the code (especially the GetField("EventClick"... part GetField("EventClick"... !), So I can do the same with other controls. For example, I want to remove the TextChanged event for a TextBox . And I also want to know how reattach the event handler.

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

Using the code above, textBox1 will have a function like placeholder. Perhaps you can just give me some help on how to add a placeholder to the text box. This is what I want.

+4
source share
2 answers

Here is the solution to your problem, according to this post .

These helper methods allow you to manipulate any event for a specific control:

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

and then you can use them to temporarily detach the event handler:

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

If you want to know what is really happening here, read on.

Windows Forms uses the EventHandlerList class to save management events. Access to each event is carried out using a simple key of the type object. Keys are stored in the private fields of the control. The only way to access this data is through reflection, but we need to know the name of the event key field. By decompiling the Control class and its descendants, we see that the keys use different names. I extracted three common naming patterns among the keys and used them in the GetControlEventKey method.

This is the mechanism that WinForms controls use to store event handlers. This is not a special thing. It is just a design choice.

+3
source

Delete

 Mybutton.event -= methodname; 

Attach

 Mybutton.event += methodname; 
+4
source

All Articles