Entwickler-Ecke
WinForms - Zugriff auf Formularelement
proggy - Di 31.03.09 13:41
Titel: Zugriff auf Formularelement
Hallo,
leider komme ich nicht weiter (mehrstündiges Probieren). Also:
Es geht um eine Windows-Forms-Anwendung. Die Klasse Form1 enthält ein Textfeld, in welches ich über dessen Eigenschaft .text eben einen solchen hineinschreiben will.
Das Problem ist jetzt aber, daß ich im gleichen Namespace zwei Klassen habe, die sich aber in zwei verschiedenen Dateien befinden. Und ich kriegs nicht hin, aus der zweiten Klasse in das Textfeld der Forms-Klasse etwas zu schreiben.
Erstelle ich mit
eine Instanz f1, so kann ich in der IDE zwar das Textfeld sehen (f1.textbox1.text), aber während der Laufzeit schreibt er trotdem nix hinein.
Wo liegt mein Fehler (Denkfehler)? DANKE!
PS.: Auch eine Vererbung bringt mich nicht weiter.
Moderiert von
Christian S.: Code- durch C#-Tags ersetzt
JüTho - Di 31.03.09 14:09
Hallo,
du schreibst nichts davon, wozu die andere Klasse da ist und was sie mit dem Formular zu tun haben soll. Ein Grundsatz der OOP ist, dass ein Objekt (hier: die andere Klasse) keinen direkten Zugriff auf Interna eines anderen Objektes (hier: das Formular) haben darf. Die Kommunikation zwischen Klassen läuft nur über definierte Schnittstellen (dieser Begriff hat nichts mit dem Schlüsselwort interface von C# zu tun).
Konkret: Von außen darf die TextBox1 gar nicht sichtbar sein - Zugriff als private deklariert. In einem solchen Fall kann man über Methoden oder Eigenschaften auf das Formular zugreifen; nur das Formular selbst weiß, was es mit diesen Informationen anzufangen hat. Nicht sehr schönes Mini-Beispiel, in dem die "andere" Klasse von der program.cs einen Verweis f1 auf die Form1-Instanz bekommt.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| public string TextBoxText { get { return textbox1.Text; } set { textbox1.Text = value; } }
f1.TextBoxText = "Beschriftung ändern"; |
Oder so:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| public void SetTextBoxText(string value) { textbox1.Text = value; }
f1.SetTextBoxText( "Beschriftung ändern" ); |
Ausführliche Erläuterungen zu dieser Problematik sind zu finden unter
[FAQ] Kommunikation von 2 Forms [
http://www.mycsharp.de/wbb2/thread.php?threadid=5960] und den dortigen Querverweisen (was über zwei Formulare gesagt ist, gilt weitgehend auch für jede andere Klasse).
Vielleicht machst du aber auch einen viel primitiveren Fehler, das geht aus Beschreibung und Code nicht hervor. Wenn du innerhalb des Formulars einen Aufruf wie "f1 = new Form1" setzt, sieht die IDE natürlich alle Elemente dieser Klasse (denn es ist ja die eigene); aber weil damit ein neues Formular erzeugt wird, kannst du damit gar nichts anfangen. Merke: "new" erzeugt immer ein neues Objekt und liefert niemals das vorhandene.
Jürgen
proggy - Di 31.03.09 14:12
Hallo,
danke!! Also mittels Getter und Setter auf das Textfeld zugreifen!?? Okay, dann dürfte ich es hinbekommen. Werds nachher mal testen.
Gruß
Andreas
proggy - Mi 01.04.09 15:21
Hallo,
hab das mal ausprobiert, aber es funktioniert leider nicht. Es handelt sich um eine Client-Server-Anwendung. Ist es richtig, daß im obigen Beispiel von JüTHO
C#-Quelltext
1:
| f1.TextBoxText = "Beschriftung ändern"; |
steht.
Müsste es nicht
C#-Quelltext
1:
| Form1.TextBoxText = ....... |
heissen?
Moderiert von
Christian S.: Code- durch C#-Tags ersetzt
JüTho - Mi 01.04.09 16:12
proggy hat folgendes geschrieben : |
Müsste es nicht
Quelltext 1:
| Form1.TextBoxText = ....... |
heissen? |
Nein, keinesfalls. Form1 ist der Name der Klasse (solche durchnummerierten Namen gehören verboten, aber nun ja...). Aber die Festlegung (egal, ob mit einer Eigenschaft oder mit einer Methode) muss bei einem speziellen Objekt vorgenommen werden.
Warum es nicht klappt, kann ich nicht beantworten, weil meine Glaskugel zur Reparatur ist. "aber es funktioniert leider nicht" liefert ja so unglaublich umfassende Informationen. Wo und wie benutzt du Form1 und den Zugriff? Fehlermeldung durch den Compiler oder zur Laufzeit? Welche Fehlermeldung?
Jürgen
proggy - Fr 03.04.09 10:11
Also meine Form1.cs sieht diesbezüglich so aus:
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: 27: 28: 29: 30:
| namespace WindowsFormsApplication1 { public partial class Form1 : Form { Form f1; public Form1() { InitializeComponent(); }
public void SetTextBox1Text(string value) { f1 = new Form1(); f1.textBox1.Text = value; } private void Form1_Load(object sender, EventArgs e) {
}
private void button1_Click(object sender, EventArgs e) { serverthread thread_x = new serverthread(); } } } |
und hier die serverthread.cs:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| namespace WindowsFormsApplication1 { class serverthread { public void gebenamenaus() {
Form1 f1 = new Form1(); f1.SetTextBox1Text("Hallo"); } } } |
Ich habe dieses Beispiel mal eben schnell "gebastelt". Hier fehlen natürlich die netzwerkrelevanten Dinge, aber darum gehts ja hier nicht.
Moderiert von
Kha: Code- durch C#-Tags ersetzt
JüTho - Fr 03.04.09 12:39
Naja, die server-spezifischen Dinge sind schon relevant, weil die Kommunikation zwischen Server und Client besondere Probleme bringen. Aber für deine Frage ist das erst in zweiter Linie wichtig.
Ich sehe nach wie vor zwei Hauptfehler:
Zum einen hast du innerhalb der Form1-Klasse eine Instanz f1 auf "sich selbst". So etwas kenne ich nur aus statischen Elementen (wie Singleton). Schmeiß all das raus, dann ist dieser Teil korrekt. Vor allem diese Stelle ist viel einfacher:
C#-Quelltext
1: 2: 3: 4: 5:
| public void SetTextBox1Text(string value) { this.textBox1.Text = value; } |
Noch zur Erklärung: Mit "new" wird eine Instanz des betreffenden Objekts erzeugt. Diese Instanz existiert (nur) innerhalb der Methode gebenamenaus() der serverthread-Klasse. Von dort aus willst du auf diese Instanz zugreifen; innerhalb der Methode SetTextBox1Text() hat die dafür verwendete Instanz natürlich
Zugriff auf ihre eigenen Inhalte; wenn du unbedingt einen Verweis "auf sich selbst" haben willst, dann verwende
this.
Aber dazu gibt es einen zweiten Hauptfehler, nämlich der Aufruf von serverthread durch Form1.Button1.Click. Durch Form1 wird damit ein neuer serverthread erstellt, durch serverthread.gebenamenaus wird ein neues Form1 erzeugt usw. Merkst du diese Zirkel-Verknüpfung?
Dringende Empfehlung: Kümmere dich um die
Grundlagen der OOP, die Zusammenarbeit zwischen verschiedenen Klassen und den Unterschied zwischen Klasse und Instanz. Vielleicht hilft dazu
OpenBook OOP [
http://openbook.galileocomputing.de/oop/].
Gruß Jürgen
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 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!