fuechse-online  
Ingenieurbüro für Softwareentwicklung
Dr. Joachim Fuchs
  Börnhausener Berg 16
51674 Wiehl
Tel.: 02262 / 701 310
Home Beispiele Kontakt Impressum
 
 

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.