Entwickler-Ecke
WinForms - Anfänger: Wie auf Formobjekt zugreifen?
Ares - Mi 14.01.09 15:17
Titel: Anfänger: Wie auf Formobjekt zugreifen?
Hallo!
Ich habe bislang nur mit Delphi gearbeitet und mache gerade meine ersten Schritte in C#. Nun stehe ich allerdings schon beim Zugriff auf das Form-Objekt auf dem Schlau:
Ich habe ein neues Windows-Forms Projekt erstellt und damit folgenden Code erhalten:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| namespace TestProgramm { static class TestProgramm { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); }
public void MyMethod() { MachWasMitDemForm(...); } }
public class MyClass { public void MyClass() { MachWasMitDemForm(...); } } } |
Frage 1:
Wie kann ich in der Methode MachWasMitDemForm() auf das Formobjekt zugreifen? Das Objekt wurde ja nur mit "new Form1()" erstellt, ich habe also keine Variable die auf das Objekt zeigt wie das bei "Form1 myForm = new Form1()" wäre...
Frage 2:
Wie kann ich aus einer anderen Klasse aus auf das Form zugreifen? In Delphi wird zu einem Formular ja immer eine globale Variable erstellt, so das der Zugriff auf ein Form kein Problem ist. In C# scheint es das nicht zu geben, wie kann ich dort also aus einer anderen Klasse auf ein Form-Objekt zugreifen? Muss ich der Klasse immer eine Referenz auf das Form übergeben oder gibt es hierfür eine andere Lösung?
Besten Dank
Ares
JüTho - Mi 14.01.09 16:57
Hallo,
Du musst in der Tat etwas umdenken: Delphi ist nur "teilweise" objektorientiert, aber NET und C# vollständig. Das bedeutet, dass irgendeine Klasse von Details einer anderen Klasse nichts, aber auch gar nichts weiß. Die Kommunikation zwischen zwei Klassen findet nur über dafür vorbereitete Schnittstellen (das sind Schnittstellen im Sinne der OOP, aber kein interface von C#) statt. Die Aufgabe darf deshalb nicht lauten: MachWasMitForm1, sondern Form1.SollWasTun. Außerdem muss die Maßnahme "Mach was" immer dort stehen, wo sie von der Sachlogik her hingehört. Aufgaben, die zu einem Formular gehören, sollten innerhalb des Formulars deklariert und implementiert werden.
In Deiner Situation hast Du drei Klassen: TestProgramm, Form1, MyClass. TestProgramm steuert den Programmablauf. (Standardmäßig heißt diese Klasse Program.) Zusätzliche Methoden wie MyMethod haben dort nur insoweit etwas zu suchen, wie es mit dem Programmablauf zusammenhängt. In der Praxis kann ich nur folgende Situation für sinnvoll halten:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| static class TestProgramm { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); string username = String.Empty; using(LoginForm login = new LoginForm()) { if (login.ShowDialog() == DialogResult.OK) username = login.Username; } if (! String.IsNullOrEmpty(username)) { MainForm main = new MainForm(); main.Init(username); Application.Run(main); } } } |
Die Frage 1 kann also etwa so beantwortet werden: Wenn es eine Notwendigkeit gibt, kannst Du Dir mit einer Variablen den Zugriff auf das Formular verschaffen. Aber Du darfst damit nur auf public-Member zugreifen, also auf Eigenschaften, die die Kommunikation über die Schnittstelle steuern, und auf Methoden, die dafür vorgesehen sind.
Etwas schwieriger ist Frage 2 zu beantworten, weil es keine allgemeingültigen Situationen gibt. Es hängt z.B. davon ab, ob eine Instanz von MyClass vom Formular erzeugt wird oder umgekehrt und welchen Einfluss die Instanzen aufeinander haben sollen. Vereinfacht gesagt: Die erzeugende Klasse darf die erzeugte Klasse kennen, aber nicht umgekehrt. Auch für diese "Kenntnis" gilt die Beschränkung auf die Schnittstelle.
Um es noch etwas komplizierter zu machen: Wenn die erzeugte Klasse etwas in der erzeugenden Klasse erledigen soll, kann ein
Delegate benutzt werden; das entspricht in etwa einem Methodenzeiger. Wenn ein Objekt (z.B. eine Klasse, die einem Datenmodul entspricht) allen Formularen in exakt der gleichen Situation bekannt sein soll, kann es als
Singleton [
http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)] eingebaut werden.
Weitere Erläuterungen zu Deinen Verständnisproblemen findest Du z.B. unter
FAQ Kommunikation zwischen 2 Forms [
http://www.mycsharp.de/wbb2/thread.php?threadid=5960] (wie von Sebastian erwähnt) und den dort genannten Verweisen.
Viel Erfolg! Jürgen
Weitere einführende Literatur:
OpenBook Visual C# [
http://openbook.galileocomputing.de/visual_csharp/]
OpenBook C# [
http://www.galileocomputing.de/openbook/csharp/]
OpenBook OOP [
http://www.galileocomputing.de/openbook/oo/]
Ares - Mi 14.01.09 18:17
Vielen Dank für eure Antworten. Diese und die Verweise auf die anderen Quellen waren schon einmal sehr hilfreich.
Ein paar Verständnisprobleme habe ich trotzdem noch:
Frage 1:
Habe ich es richtig verstanden, dass in der "Hauptklasse" Programm und der Methode static void Main() {...} im Allgemeinen nichts anderes gemacht werden soll als das Programm zu starten? Außer dem automatisch erzeugten Code sollte man hier nur was einfügen wenn man einen wirklich guten Grund dafür hat. Alles weitere (im Allgemeinen) sollte lieber aus der Form-Klasse gestartet / gesteuert werden. Habe ich das richtig verstanden?
Frage 2:
Objekt A erzeugt Objekt B. In diesem Fall sollte Objekt B prinzipiell nichts von Objekt A wissen und folglich auch nicht auf dieses zugreifen. Muss B an A dennoch unbedingt Änderungen vornehmen sollte man das über über Events oder Delegates regeln. Richtig verstanden?
Solche Fälle habe ich bislang immer so geregelt, dass Objekt A in Objekt B als Parent bekannt ist:
C#-Quelltext
1: 2: 3: 4: 5:
| ObjektB objB = new ObjektB(this);
Parent.MachWas(...); |
Was spricht gegen ein solches vorgehen bzw. was ist an Delegates und Events als an einem solchen Parent-Verweis?
Besten Dank
Ares
JüTho - Mi 14.01.09 18:23
Ares hat folgendes geschrieben : |
Frage 1:
Habe ich es richtig verstanden, dass in der "Hauptklasse" Programm und der Methode static void Main() {...} im Allgemeinen nichts anderes gemacht werden soll als das Programm zu starten? Außer dem automatisch erzeugten Code sollte man hier nur was einfügen wenn man einen wirklich guten Grund dafür hat. Alles weitere (im Allgemeinen) sollte lieber aus der Form-Klasse gestartet / gesteuert werden. Habe ich das richtig verstanden? |
Ja.
Ares hat folgendes geschrieben : |
Frage 2:
Objekt A erzeugt Objekt B. In diesem Fall sollte Objekt B prinzipiell nichts von Objekt A wissen und folglich auch nicht auf dieses zugreifen. Muss B an A dennoch unbedingt Änderungen vornehmen sollte man das über über Events oder Delegates regeln. Richtig verstanden? |
Ja.
Ares hat folgendes geschrieben : |
Solche Fälle habe ich bislang immer so geregelt, dass Objekt A in Objekt B als Parent bekannt ist:
C#-Quelltext 1: 2: 3: 4: 5:
| ObjektB objB = new ObjektB(this);
Parent.MachWas(...); |
Was spricht gegen ein solches vorgehen ... |
Es gibt Situationen, in denen das Verfahren über Parent sinnvoll ist.
Ich würde das aber möglichst vermeiden.
Gruß Jürgen
Ares - Mi 14.01.09 18:27
JüTho hat folgendes geschrieben : |
Es gibt Situationen, in denen das Verfahren über Parent sinnvoll ist. Ich würde das aber möglichst vermeiden.
|
Aus Gründen des Geschmacks oder gibt es hierfür auch ganz praktische Gründe?
Christian S. - Mi 14.01.09 18:32
Aus Gründen einer korrekten Kapselung.
Mit Deiner Methode ist Objekt B dafür verantwortlich, dass in Objekt A etwas passiert. Wenn Du es über ein Event machst, ist alleine Objekt A dafür verantwortlich, auf dieses Event zu reagieren. Das ist zum einen eine saubere Trennung (B muss nichts über die Implementationsdetails von A wissen), zum anderen hat es auch den praktischen Vorteil, dass Du bei einer Änderung in A nicht auch B ändern musst.
Hobbyprg - Fr 30.01.09 22:44
Schöner Link (kannte ich noch gar nicht) :zustimm:
Den C# Grundlagen habe ich mir dann gleich auch noch
mal zu Gemüte geführt. 8)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!