如何在C#中删除并重新查看EventHandler到控件? [英] How to remove and re-attatch EventHandler to controls in c#?

查看:1074
本文介绍了如何在C#中删除并重新查看EventHandler到控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读此答案
它只是告诉我如何从按钮控件中删除点击事件。我想知道如何更改代码(特别是 GetField(EventClick... part!),所以我可以用其他控件做同样的事情,我想删除 TextBox TextChanged 事件
我也想知道如何重新 - 附加事件处理程序。

  public partial class Form1:Form 
{
public Form1()
{
InitializeComponent();
}

private void textBox1_TextChanged(object sender,EventArgs e)
{
if(textBox1.Text。长度< 10)return;

MessageBox.Show(do something);
}

private void Form1_Load(object sender,EventArgs e)
{
Tools.mkTextBoxWithPlaceholder(textBox1,hi,input here ...);
}
}
类工具
{
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在此处删除TextChanged事件处理程序。

tb.Text = tb.Tag作为字符串;

// TODO在这里重新连接TextChanged事件处理程序。
}
}

使用上面的代码,textBox1将有一个函数像占位符。也许您可以给我一些关于如何将占位符添加到文本框的帮助。这是我想要的。

解决方案

根据我的这个帖子



这些帮助方法可以让您操纵特定控件的任何事件:

  //还搜索继承层次结构
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);
返回fi;
}

私有静态对象GetControlEventKey(Control c,string eventName)
{
类型type = c.GetType();
FieldInfo eventKeyField = GetStaticNonPublicFieldInfo(type,Event+ eventName);
if(eventKeyField == null)
{
if(eventName.EndsWith(Changed))
eventKeyField = GetStaticNonPublicFieldInfo(type,Event+ eventName.Remove(eventName 。长度 - 7)); //删除已更改
else
eventKeyField = GetStaticNonPublicFieldInfo(type,EVENT_+ eventName.ToUpper());
if(eventKeyField == null)
{
//不是WinForms控件中的所有事件都使用此模式。
//如果需要,可以使用其他方法来搜索事件处理程序。
返回null;
}
}
return eventKeyField.GetValue(c);
}

private static EventHandlerList GetControlEventHandlerList(Control c)
{
类型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);

//删除处理程序
var handlers = eventList [eventKey];
eventList.RemoveHandler(eventKey,处理程序);

// ...执行你的任务

//重新附加处理程序
eventList.AddHandler(eventKey,handler);
}

如果你想知道这里发生了什么,请继续阅读。 p>

Windows窗体使用 EventHandlerList 类来维护控制事件。使用类型对象的简单键访问每个事件。密钥存储在控件的私有域中。访问此数据的唯一方法是使用反射,但我们应该知道事件键字段的名称。通过反编译 Control 类和它的后代,我们可以看到这些键使用不同的名字。我提取了键之间的三个常见的命名模式,并在 GetControlEventKey 方法中使用它们。



这是机制WinForms控制用于保存事件处理程序。没有什么特别的事情。这只是一个设计选择。


I've read this answer. It just tell me how to remove the click event from a button control. I want to know how to change the code (especially the GetField("EventClick"... part!) so I can do the same thing with other controls. For example, I want to remove the TextChanged event of a TextBox. And I also want to know how to re-attach 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.
    }
}

With the code above, the textBox1 will have a function like placeholder.Maybe you can just give me some help on how to add the placeholder to a textbox. That's what I want.

解决方案

Here is a solution to your problem, according to this post of mine.

These helper methods let you 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 an 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 maintain control events. Every event is accessed using a simple key of type object. Keys are stored in private fields of the control. The only way to access this data is using reflection, but we should know the name of the event key field. By decompiling the the Control class and it's descendants, we can see that the keys use different names. I extracted three common naming pattern among the keys, and used them in the GetControlEventKey method.

This is the mechanism that WinForms controls use to hold the event handlers. There is no special thing about it. It is just a design choice.

这篇关于如何在C#中删除并重新查看EventHandler到控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆