Dialoge sinnvoll kapseln in C#
Teil 2 Hinzufügen einer "Übernehmen" - Taste
Im
ersten Teil wurde gezeigt, wie man in .net Dialoge mit
Hilfe der objektorientierten Programmierung kapseln und
universell einsetzen kann. Das Beispiel wird jetzt um eine
gängige Funktionalität von Dialogen erweitert:
Der Dialog soll um eine weitere Taste
ergänzt werden, die es gestattet, Änderungen in den
Eingabefeldern sofort in die Daten zu übertragen. Das
Hauptfenster muss über die Änderungen informiert werden und die
eigene Anzeige neu aufbauen. Der Dialog sieht dann
folgendermaßen aus:

Für die Benachrichtigung des Hauptfensters
gibt es verschiedene Möglichkeiten. Ein direkter Aufruf
spezifischer Funktionen der Hauptfensterklasse verbietet sich
von selbst, da er die Kapselung durchbrechen würde. Der Dialog
soll ja unabhängig vom Aufrufer sein. Vielleicht soll er später
einmal in einem anderen Kontext verwendet werden.
Eine Alternative ist der Einsatz von
Interfaces. Der Dialog könnte sich darauf verlassen, dass der
Aufrufer eine bestimmte Schnittstelle implementiert und über
eine zusätzlich übergebene Referenz des Hauptfensterobjektes
Methoden dieser Schnittstelle aufrufen.
Der elegantere und in .net üblichere Weg
ist jedoch über ein Delegate. Delegates sind so etwas wie
benannte Methodensignaturen und Funktionszeiger. Ein Delegate
selbst ist eine Klasse, die irgendwo definiert werden muss. Es
bietet sich an, diese Definition in der Dialogdatei vorzunehmen.
Sie kann auch als innere Klasse der Dialogklasse angelegt
werden. Die Definition des Delegates unterscheidet sich von der
anderer Klassen, da der Compiler zusätzliche Vorkehrungen
trifft. Hier die Definition für die benötigte Delegate-Klasse:

Damit wird eine Klasse definiert, die im
gesamten Namespace unter dem Namen
DialogFahrzeug.DatenÜbernehmenDelegate bekannt ist.
Innerhalb der Dialogklasse benötigen wir eine Referenzvariable
dieses Typs. Sie verweist später auf die Methode, die aufgerufen
werden soll, wenn die Übernehmen-Taste gedrückt wird.

Wie wird nun die Referenz auf die passende
Rückrufmethode gesetzt?
Da die Membervariable
DatenÜbernehmenRückruf privat ist und auch sein sollte,
müssen wir in der Methode Anzeigen einen
zusätzlichen Parameter anlegen und die Variable setzen:

Im rufenden Programm muss nun eine Methode
für den Rückruf bereitgestellt werden. Diese Methode muss exakt
die gleiche Signatur besitzen, wie in dem Delegate definiert.
Sie muss also in Parameterliste und Rückgabetyp
DatenÜbernehmenDelegate entsprechen. Der Name der
Methode spielt keine Rolle, auch nicht der Zugriffsmodifizierer
(public, private etc.).

In diesem einfachen Fall genügt es, wie in
Teil 1 beschrieben, den aktuellen Eintrag der Listbox mit den
geänderten Daten zu aktualisieren. Die Daten werden als
Parameter übergeben. Bei diesem Beispiel könnte man sogar auf
den Parameter verzichten, da wir auch im Hauptfenster immer noch
die Referenz auf das Datenobjekt halten. In vielen Fällen wird
es jedoch unumgänglich sein, der Methode die neuen Daten
mitzugeben.
Auf der rufenden Seite muss jetzt noch der
Aufruf von DialogFahrzeug.Anzeigen angepasst
werden. Der zusätzliche Parameter ist eine Referenz einer
Instanz der Klasse DatenÜbernehmenDelegate. Das
klingt komplizierter als es ist:

Hier wird deutlich, dass
DialogFahrzeug.DatenÜbernehmenDelegate eine Klasse ist,
die mit new instanziiert wird.
Die syntaktische Besonderheit ist der Parameter, der dem
Konstruktor übergeben wird: Es ist der Name einer Methode, die
der Delegate-Signatur entsprechen muss. Der Compiler erledigt
den Rest.
Abschließend müssen wir nun in der
Dialogklasse dafür sorgen, dass nach Betätigung der
Übernehmen-Taste die Daten aus den Steuerelementen
gelesen werden und die Rückrufmethode aufgerufen wird.
Zunächst benötigen wir einen Verweis auf
die Daten als Membervariable, damit wir innerhalb einer
Ereignis-Methode darauf zugreifen können. Bislang steht uns
dieser Verweis nur innerhalb der statischen Methode
Anzeigen zur Verfügung. Wir müssen uns diese Referenz
daher dort merken:

Nun benötigen wir eine Ereignis-Methode für
das Click-Ereignis der Taste. Dort werden die Werte eingelesen,
in das Datenobjekt übertragen und die Rückrufmethode aufgerufen:

Der Aufruf der Rückrufmethode geschieht
hier ganz einfach, indem statt eines Methodennamens die
Membervariable DatenÜbernehmenRückruf eingesetzt
wird. Der Compiler sorgt automatisch dafür, dass zur Laufzeit
die Methode aufgerufen wird, die wir als Parameter beim Aufruf
von Anzeigen übergeben haben.
Das Programm ist jetzt fertig. Zum Testen
wählt man einen Eintrag in der Listbox aus, öffnet den Dialog,
ändert die Einträge und klickt auf die Übernehmen-Taste.
Die geänderten Daten werden dann sofort in der Listbox
angezeigt.
Auch dieses Projekt steht zum
Download bereit.
Der Ablauf im Überblick
Abschließend noch einmal der Kontroll- und
Datenfluss bei Programmablauf:
Nach Auswahl eines Listbox-Eintrags und
Betätigen der Ändern-Taste wird die statische
Methode DialogFahrzeug.Anzeigen
aufgerufen. Dieser werden sowohl die Daten als auch die
Referenz (Adresse) einer Rückrufmethode übergeben.
DialogFahrzeug.Anzeigen legt
eine Instanz der Dialogklasse an und speichert die Verweise auf
Daten und Rückrufmethode in Membervariablen dieser Instanz.
Anschließend wird der Dialog angezeigt.
In ÄnderungenÜbernehmen_Click
werden die Daten geändert und die angegebene Rückrufmethode
aufgerufen.
Ausblick
Im nächsten Teil wird gezeigt, wie man die
vorliegende Dialogklasse als Basis für weitere Dialoge verwenden
kann.
|