以编程方式使用事件处理程序的C#+
问题描述:
我有一个TextBox,它声明式地设置了TextChanged事件。在某些情况下,我希望以编程方式设置此值。在这些情况下,我想禁用TextChanged事件,直到以编程方式完成设置值为止。然后,当我完成时,我想恢复事件处理程序的行为。以编程方式使用事件处理程序的C#+
对于一个文本框,我知道我可以通过以下操作实现这一点:
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;
}
不幸的是,这种方法不起作用。它甚至不会编译。有没有一种方法可以封装我正在试图在上面显示的方法中完成的功能?如果是这样,怎么样?
谢谢,
答
你基本上不能。事件公开的唯一功能是订阅和取消订阅 - 你不能要求一组现有的处理程序。如果现有的处理程序在您的代码中,您可以设置一些标志,意思是“忽略此刻引发的任何更改” - 但无法有效地删除所有其他处理程序。
答
我认为乔恩是对的。不过,我认为你从错误的角度来看问题。
在这种情况下,您实际上想要更改TextBox的行为,我的首选项是子类TextBox,添加一个布尔型标志FireOnTextChanged,并且只在布尔值为true时触发该事件。这样你就不必担心加载和/或卸载事件处理程序。
答
您可以创建派生文本框,覆盖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.
}
}
}
答
我不知道,但我认为这是可以做到这样的:
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);
}
}
UPDATE
Clone()
来自using System.Linq;