2 Stimmen

C# + Programmgesteuertes Arbeiten mit Ereignishandlern

Ich habe ein TextBox, bei dem das TextChanged-Ereignis deklarativ festgelegt ist. In einigen Fällen möchte ich diesen Wert programmgesteuert setzen. In diesen Fällen möchte ich das TextChanged-Ereignis deaktivieren, bis ich den Wert programmgesteuert gesetzt habe. Dann, wenn ich fertig bin, möchte ich den Ereignishandler wiederherstellen, um sich so zu verhalten, wie er war.

Für ein einzelnes TextBox kann ich dies wie folgt erreichen:

myTextBox.TextChanged -= myTextBox_TextChanged;
myTextBox.Text = "[Ein Wert]";
myTextBox.TextChanged += myTextBox_TextChanged;

Ich möchte jedoch diese Funktionalität in eine einzige Methode schreiben, auf die von mehreren Methoden aus zugegriffen werden kann. Ich versuche beispielsweise Folgendes zu tun:

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

Leider funktioniert dieser Ansatz nicht. Es kompiliert nicht einmal. Gibt es einen Weg, wie ich die Funktionalität, die ich oben gezeigt habe, in einer Methode wie der oben gezeigten encapsulieren kann? Wenn ja, wie?

Vielen Dank,

3voto

Jon Skeet Punkte 1325502

Grundsätzlich geht das nicht. Die einzige Funktionalität, die ein Ereignis bietet, ist das Abonnieren und Abbestellen - du kannst nicht nach der Gruppe der vorhandenen Handler fragen. Wenn der vorhandene Handler in deinem Code ist, könntest du einen Flag setzen, das bedeutet "ignoriere jegliche Änderungen vorübergehend" - aber du kannst nicht effektiv alle anderen Handler entfernen.

3voto

gͫrͣeͬeͨn Punkte 3646

Ich denke, Jon hat recht. Allerdings glaube ich, dass du das Problem aus dem falschen Blickwinkel angehst.

In einem Fall wie diesem, wo du tatsächlich versuchst, das Verhalten eines TextBox zu ändern, wäre meine Vorliebe, die TextBox zu subklassieren, ein boolesches Flag "FireOnTextChanged" hinzuzufügen und das Ereignis nur auszulösen, wenn der boolesche Wert wahr ist. Auf diese Weise musst du dir keine Gedanken darüber machen, die Ereignishandler zu laden und/oder zu entladen.

2voto

Jacob G Punkte 3585

Sie könnten ein abgeleitetes Textfeld erstellen, das das TextChanged-Ereignis überschreibt, um die Handler-Add/Remove-Aufrufe zu erfassen.

public MyTextbox:Textbox
{
    public Event EventHandler TextChanged
    {
        add
        {
           //setzen der Basis
           //lokal speichern
        }
        remove
        {
           //von Basis entfernen
           //aus lokalem Speicher entfernen
        }
    }

    public string Text
    {
        get
        {
            //die Basis zurückgeben
        }
        set
        {
           //lokale Handler von Basis entfernen
           //Wert in Basis setzen
           //Handler neu zuweisen
        }
    }
}

0voto

Janusz Skonieczny Punkte 15373

Siehe MulticastDelegate

Ich bin mir nicht sicher, aber ich denke, es ist möglich, etwas wie folgt zu tun:

    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() kommt von using System.Linq;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X