C#+以编程方式使用事件处理程序

时间:2010-03-18 16:13:29

标签: c#

我有一个TextBox,它以声明方式设置了TextChanged事件。在某些情况下,我想以编程方式设置此值。在这些情况下,我想禁用TextChanged事件,直到我以编程方式设置值。然后,当我完成后,我想恢复事件处理程序以保持原样。

对于单个TextBox,我知道我可以通过执行以下操作来实现此目的:

myTextBox.TextChanged -= myTextBox_TextChanged;
myTextBox.Text = "[Some Value]";
myTextBox.TextChanged += myTextBox_TextChanged;

但是,我想将此功能写入一个可以通过多种方法访问的方法。例如,我正在尝试这样做,如下所示

private void UpdateTextValue(TextBox textBox, string newValue)
{
  object eventHandler = textBox.TextChanged;
  textBox.TextChanged -= eventHandler;
  textBox.Text = newValue;
  textBox.TextChanged += eventHandler;
}

不幸的是,这种方法不起作用。它甚至不会编译。有没有办法可以封装我试图在上面显示的方法中完成的功能?如果是这样,怎么样?

谢谢,

4 个答案:

答案 0 :(得分:3)

基本上,你不能。事件暴露的唯一功能是订阅和取消订阅 - 您不能要求现有的处理程序集。如果现有的处理程序在您的代码中,您可以设置一些标记,意思是“忽略当前引发的任何更改” - 但是您无法有效地删除所有其他处理程序。

答案 1 :(得分:3)

我认为乔恩是对的。但是,我认为你是从错误的角度来解决这个问题。

在这种情况下,你实际上试图改变TextBox的行为,我的偏好是子类TextBox,添加一个布尔标志FireOnTextChanged,并且只有在boolean值为true时才触发事件。这样您就不必担心加载和/或卸载事件处理程序。

答案 2 :(得分:2)

您可以创建派生文本框,覆盖TextChanged事件以捕获处理程序添加/删除调用。

public MyTextbox:Textbox
{
    public Event EventHandler TextChanged
    {
        add
        {
           //set the base
           //store locally
        }
        remove
        {
           //remove from base
           //remove from local store
        }
    }

    public string Text
    {
        get
        {
            //return the base
        }
        set
        {
           //remove local handlers from base
           //set value in base
           //reassign handlers.
        }
    }
}

答案 3 :(得分:0)

请参阅MulticastDelegate

我不确定,但我认为可以这样做:

    Delegate[] invocationList = TextChanged.GetInvocationList().Clone();
    foreach (EventHandler h in invocationList) {
        try {
            TextChanged -= h
        } catch (Exception exception) {
            Console.WriteLine(exception.Message);
        }
    }
    foreach (EventHandler h in invocationList) {
        try {
            TextChanged += h
        } catch (Exception exception) {
            Console.WriteLine(exception.Message);
        }
    }

<强>更新

Clone()来自using System.Linq;