C# + Programmatically Working with Event Handlers
I have a TextBox that has the TextChanged event set declaratively. In some cases, I want programmatically set this value. In these cases, I want to disable the TextChanged event until I'm done programmatically setting the value. Then, when I'm done, I want to restore the event handler to behave as it was.
For a single TextBox, I know I can accomplish this by doing the following:
myTex开发者_Python百科tBox.TextChanged -= myTextBox_TextChanged;
myTextBox.Text = "[Some Value]";
myTextBox.TextChanged += myTextBox_TextChanged;
However, I want to write this functionality into a single method that can be accessed by several methods. For instance, I'm trying to do so something like the following
private void UpdateTextValue(TextBox textBox, string newValue)
{
object eventHandler = textBox.TextChanged;
textBox.TextChanged -= eventHandler;
textBox.Text = newValue;
textBox.TextChanged += eventHandler;
}
Unfortunately, this approach doesn't work. It won't even compile. Is there a way I can encapsulate the functionality I'm trying to accomplish in a method such as the one shown above? If so, how?
Thank you,
You can't, basically. The only functionality an event exposes is subscribe and unsubscribe - you can't ask for the set of existing handlers. If the existing handler is in your code, you could set some flag meaning "ignore any changes raised for the moment" - but you can't effectively remove all the other handlers.
I think Jon's right. However, I think you're approaching the problem from the wrong angle.
In a case like this, where you're actually trying to change the behaviour of a TextBox, my preference would be to sub-class TextBox, add a boolean flag FireOnTextChanged and only fire the event if the boolean value is true. That way you don't have to worry about loading and/or unloading the event handlers.
You could create a derived Textbox, override the TextChanged event to capture the handler Add/Remove calls.
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.
}
}
}
See MulticastDelegate
I'm not sure but I think it's possible to do something like:
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()
comes from using System.Linq;
精彩评论