Workshop UserControls Part 2: Bedienung bitte! - Über Click, KeyPress und Mnemonics

24. Mai 2009 von Werner Mager · Gelesen: 1432 · heute: 4

Im zweiten Teil meines kleinen Workshops möchte ich auf Events, speziell auf den Click-Event eingehen. Was auf den ersten Blick recht einfach anmutet, erfordert doch einen gewissen Aufwand, wenn eine konsistente Bedienung inklusive der Unterstützung von Tastatur-Events und Mnemonics (&-Shortcuts) erreicht werden soll.

Der Click-Event
Damit sich unsere Schaltfläche aus Teil 1 des Workshops auch tatsächlich als Schaltfläche verhält, wird eine sinnvolle Implementierung des Click-Events benötigt. Wie jedes Control besitzt die Klasse UserControl bereits einen ClickEvent. Dieser wird jedoch nur ausgelöst, wenn auch tatsächlich auf das UserControl geklickt wird. Wird stattdessen z.B. auf das Label in dem UserControl geklickt, wird der Click-Event nicht ausgelöst.

Folglich müssen wir von allen Untergeordneten Controls den ClickEvent abonieren und mit diesem ein Click Auslösen, was ein Eventsammler für uns erledigt.

Eventsammler
Über eine rekursive Methode wird der Click-Event aller untergeordneten Controls aboniert:

public SomeButton() {
    InitializeComponent();
    RegisterEvents(this);
}
 
void RegisterEvents(Control parent) {
    foreach (Control child in parent.Controls) {
        child.Click += new System.EventHandler(child_Click);
        RegisterEvents(child);
    }
}

Abfeuern des ClickEvents
Nun bleibt die Frage, wie wir selbst den Click Event unseres Controls auslösen können. Der erste Ansatz, den Event mit “override” zu überschreiben schlägt fehl, da der Event nicht als “virtual” definiert ist. Nun könnte man versucht sein, den Event einfach auszublenden und den neuen Event wie folgt zu definieren:

public new event EventHandler Click;

Hiervon sei aber dringend abzuraten!!! Wird unsere Componente nämlich als Componente betrachtet und auf sie der Click Event registriert (z.B. so wie wir es in der Methode “RegisterEvents” gemacht haben ), so wird nicht der neue, sondern der Event der Basisklasse abonniert. Also gilt: NEVER DO THAT!

Stattdessen ist auf die Methode base.OnClick(EventArgs e) zurück zugreifen. Diese Methode löst den Click-Event aus:

void child_Click(object sender, System.EventArgs e) {
    base.OnClick(e);
}

Click als Standard
Ein kleines Detail fehlt dem Click-Event noch; damit dieser standardmäßig angelegt wird, wenn im Designer auf unser Control ein Doppelclick ausgeführt wird, müssen wir unere Class UserControl mit dem Attribut [DefaultEvent(”Click”)] versehen.

Schon hat sich unser Control in einen funktionierenden Button verwandelt. Wobei die Button-Funktionalität noch nicht volständig gegeben ist. Unser Button reagiert nicht auf Tastatureingabe.

Tastatureingabe
Um auf Tastatureingabe zu reagieren, ist es nicht nötig, von allen untergeordneten Controls das KeyDown-Event zu abonieren, da ein KeyDown nur von einem Control ausgelöst werden kann, dass den EingabeFocus hat. Folglich reicht es, für unser UserControll selbst den KeyDown-Event zu abonieren. Dies kann z.B. über die Design-Ansicht gemacht werden (Properties-Fenster auf Events umschalten und dort ein Doppelklick auf KeyDown) oder natürlich auch als Code im Konstruktor der Klasse.

In der KeyDown-Eventmethode wird nun einfach überprüft, ob der Benutzer Space oder Enter gedrückt hat und entsprechend ein Click-event ausgelöst:

private void SomeButton_KeyDown(object sender, KeyEventArgs e) {
    if (e.KeyCode == Keys.Space || e.KeyCode == Keys.Enter) {
        base.OnClick(e);
    }
}

Nun können Per Tab-Taste die Buttons ausgewählt und mit Space oder Enter bestätigt werden. Der einzige Hacken ist nur, dass der Benutzer nicht erkennen kann, welcher Button gerade den Focus hat. Dieses Problem wird in Teil 3 dieses Workshops angesprochen.

Mnemonics
Der Begriff Mnemonic bedeutet “Gedächtnisstütze” vom griechischen mnēmoniká “Gedächtnis”. Im Context Windows Applikation steht er für die Sortcuts, die bei Betätigung der ALT-Taste in Form eines unterstrichenen Buchstabens angezeigt werden. Dieser Buchstabe wird vom Entwickler festgelegt, in dem ihm ein & vorangestellt wird. Das & erscheint nicht auf dem Button. (Soll dagegen Tatsächlich ein & auf dem Button stehen, so müssen zwei & angegeben werden.)

Wenn wir nun wollen, dass unser UserControl auf ein Mnemonic reagiert, reicht es aber leider nicht, in die Text-Property ein & einzufügen. Der nachfolgende Buchstabe wird zwar unterstrichen, sobald man die ALT-Taste drückt, ein Click wird jedoch nicht ausgelöst.
Der Trick besteht nun darin, dass die Methode “ProcessMnemonic” überschrieben werden muss. Diese Methode wird aufgerufen, wenn der Benutzer eine mögliche Tastenkombination gedrückt hat. Der statischen methode Control.isMnemotic() wird der Wert der Text-Property unseres Controls übergeben und es wird ausgewertet, ob diese Tatsächlich der Mnemonic dieses Controls war. Bei positiver Rückgabe ein Click ausgelöst.

Implementiert wird dies wie folgt:

protected override bool ProcessMnemonic(char charCode) {
    if (Control.IsMnemonic(charCode, this.Text)) {
        base.OnClick(new EventArgs());
        return (true);
    } else {
        return base.ProcessMnemonic(charCode);
    }
}

Zu guter Letzt
Hier endet nun auch der zweite Teil des UserControl-Workshops. Im dritten Teil werde ich noch tiefer auf Events eingehen, insbesondere werde ich die MouseEnter, MouseLeave und die Focus Events behandeln, so dass sich unser Control noch intuitiver verhält.

Wie immer gibt es an dieser Stelle das komplette Projekt zum Download:

Visual Studio Pojekt “UserControlworkShopPart2″

Eine Antwort zu “Workshop UserControls Part 2: Bedienung bitte! - Über Click, KeyPress und Mnemonics”

  1. Sternico: Inside» Blogarchiv » Workshop UserControls Part 1: Getting Started sagt:

    […] vorheriger Artikel nächster Artikel […]

Hinterlasse eine Antwort