Von UserControl auf Startform zugreifen..!
-
Hallo liebes Forum,
habe folgendes problem und bitte um Rat.
Habe eine StartForm ("Form1"), die in zwei panels geteilt ist (Panel1 und Panel2).
Im Panel2 wird beim Start ein UserControl geladen. Im Panel1 befindet sich ein Label, das public ist.
Im UserControl befindet sich ein button, mit dem man, wenn der gedrückt wird den Text in Label von Panel1 ändern soll.
Hier der Code:// In UserControl Form1 frm = new Form1(); frm.label1.Text = "Was"; // zugriff auf laebel von Panel1 in Form1
Der obere Code funktioniert nicht. Der Label.Text ändert sich nicht.
Wenn ich hingegen das schreibe:
Form1 frm = new Form1(); frm.label1.Text = "Was"; frm.Show();
...dann ändert sich zwar der Label-text aber in einem neuen Fenster.
Das alte Fenster bleibt so wie es war..!Was kann ich machen um den Label-text zu ändern aber ohne ein neues Fenster öffnen zu müssen...?
-
Wenn du schreibst "new Form", wird natürlich ein neues Formular angelegt - du müßtest also an das bestehende Formular herankommen: entweder als Referenz dem UserControl übergeben oder aber mittels der FindForm-Methode.
Jedoch durchbricht deine Vorgehensweise das Kapselungsprinzip: untergeordnete Objekte sollten keinen direkten Zugriff auf übergeordnete haben.
Hierfür ist es besser, du definierst dir ein Event im UserControl und die Form abonniert dieses dann und führt dort dann den Zugriff auf das Panel aus (denn direkter Zugriff auf Controls sollte nur die eigene Form-Klasse durchführen!!!).
Hier noch zwei FAQs zum Thema (aus einem anderen Forum):
http://www.mycsharp.de/wbb2/thread.php?threadid=5960
http://www.mycsharp.de/wbb2/thread.php?threadid=26116Und hier noch der Link aus dieser FAQ:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39763.html
-
Danke dir, werde mich mal mit dem Thema befassen..!
Melde mich wieder wenn ich ein problem finde..!Auf jeden Fall DANKE..!
-
Muss schon sagen einen eigenen Event zu erstellen ist schwieriger als ich dachte.
Du meintest ich soll den Event in UserControl definieren.Meintest du nicht in der Startform defineiren und vom UserControl abrufen..?
Oder was habe ich da falsch verstanden
Mit Hilfe des Beispieles von mycsharp.de, sieht mein Code in Form1 (Startform) so aus:public event EventHandler MyEvent; protected virtual void OnMyEvent(EventArgs e) { EventHandler myEvent = MyEvent; if (myEvent != null) { myEvent(this, e); } } public void DoSomething() { // ... OnMyEvent(EventArgs.Empty); // was kommt hier..? // etwa das..? label1.Text = "was"; // label von startform wert zuweisen }
Und in UserControl:
private void button1_Click(object sender, EventArgs e) { Form1 frm = new Form1(); frm.MyEvent += new EventHandler(frm_MyEvent); frm.DoSomething(); } void frm_MyEvent(object sender, EventArgs e) { throw new NotImplementedException(); // was kommt hier..???? }
-
Nein, ich meinte es so, wie ich geschrieben habe.
Du hast es also jetzt falsch herum (und immer noch den "new Form"-Aufruf im UserControl)!!!
Ein UserControl muß ganz für sich alleine lauffähig sein, egal auf welchem Formular es plaziert wird.
-
Ja, aber wo kommt die funtkion die dem label1.text einen string übergibt?
Also so wie du meinst, habe ich mein UserControl, wo ein Event definiert wurde:
public event EventHandler MyEvent; protected virtual void OnMyEvent(EventArgs e) { EventHandler myEvent = MyEvent; if (myEvent != null) { myEvent(this, e); } } public void DoSomething() { // ... OnMyEvent(EventArgs.Empty); // verstehe aber nicht was hier fürn befehl kommen soll?? } private void button1_Click(object sender, EventArgs e) { //??? }
So, jetzt bin ich aber verwirrt. Verstehe nicht wie ich auf Label1 von der Startform zugreifen soll, wenn alles in UserControl geschrieben wird..!
Th69 schrieb:
Nein, ich meinte es so, wie ich geschrieben habe.
Du hast es also jetzt falsch herum (und immer noch den "new Form"-Aufruf im UserControl)!!!
Ein UserControl muß ganz für sich alleine lauffähig sein, egal auf welchem Formular es plaziert wird.Wollte ja auch kein new-Aufruf benutzen, doch habe versucht es so zu machen, wie es auf der Seite da stand http://www.mycsharp.de/wbb2/thread.php?threadid=8799.
Nun leider habe ich immer noch nciht richtig verstanden wie so ein Event-erstellung funktioniert und ausser ein paar Seiten im net, finde ich auch viel zu wenige infos darüber!
-
Du hast jetzt schon fast alles richtig gemacht.
Wenn du jedoch einen variablen Text übergeben willst, benötigst du jetzt noch einen Übergabeparameter bei deinem Event (den Textstring), s. die letzten beiden Beiträge von 'programmierhans' (bis .NET 1.1) und 'ThomasR' (ab .NET 2.0): anstatt 'EventHandler' definierst du dir einen eigenen Event mit zusätzlichem Property "Text".Und in der Form abonnierst du dann dieses Event:
userControl.MyEvent += UserControl_MyEvent; private void UserControl_MyEvent(object sender, MyEventArgs e) { label1.Text = e.Text; }
(statt 'MyEvent' natürlich einen passenden Namen wählen -)
Ich hoffe, jetzt ist es dir klarer geworden?
-
Tut mir leid, dass ich dich wieder nerven muss. Habe zwar ein bishen die Logik verstanden, nur ist mir das ganze zu Fremd, um wirklich ALLES zu verstehen.
Jetzt zum Code...UserControl..:
// eigenes Event definieren public event EventHandler<labeltext> Change_labeltext; protected virtual void OnChange_labeltext(string textReceived) { EventHandler<labeltext> label_event = this.Change_labeltext; if (label_event != null) { label_event(this, new labeltext(textReceived)); } } public class labeltext : System.EventArgs { private readonly string text; public labeltext(string text) : base() { this.text = text; } public string Text { get { return this.text; } } } private void button1_Click(object sender, EventArgs e) { //wie rufe ich aber mein Event vom Button aus auf..? //bis jetzt kenne ich nur das man mit "+=" events aufrufen kann }
und Form1..:
// Hier zeigt VStudio einen Fehler an //Ungültiges Token "+=" in Klasse, Struktur oder Schnittstellenmemberdeklaration UserControl1.labeltext += UserControl1_labeltext; private void UserControl_MyEvent(object sender, MyEventArgs e) { label1.Text = e.Text; }
Meine nächste Frage wäre dann wie label1.Text den string bekommt..?
Muss ich etwa bei der labeltext-klasseprivate readonly string text="was";
..so schreiben..?
-
Aufruf in Button-Click:
private void button1_Click(object sender, EventArgs e) { OnChange_labeltext("was"); // <- du solltest hier eine bessere Benennung haben, s.u. !!! }
Und das Abonnieren mittels '+=' mußt du (natürlich) in einer Methode vornehmen, d.h. am besten im Konstruktor der Form:
MySupeDuperForm() { InitializeComponents(); userControl.TextEvent += UserControl_TextEvent; // <-- du solltest dein Event besser benennen, s.u. !!! }
Und zu deiner letzten Frage:
der Text wird eben über diese Zwischenklasse ('labeltext' bei dir) übergeben.
Laut MS-Namensgebung sollten alle von EventArgs abgeleiteten Klassen aber ebenso heißen, d.h. z.B. TextEventArgs.
D.h. auch der letzte Parameter in 'UserControl_MyEvent':private void UserControl_TextEvent(object sender, TextEventArgs e) { label1.Text = e.Text; }
So und jetzt kommt das Eigentliche:
da dem UserControl völlig egal ist, ob und wie dieser Text dargestellt wird, sollte also der Name nicht 'labeltext' heißen!
Du könntest jetzt auch einfach ein anderes Form nehmen, dort das UserControl darauf plazieren und den Text dann z.B. in eine Datei schreiben oder aber über das Internet versenden.Du mußt gedanklich einfach eine komplette Trennung von Form und UserControl vornehmen!
So und jetzt hoffe ich, verstehst du den Programmcode? -)
Ansonsten lies noch mal genau die FAQ-Beiträge durch.
-
Danke dir erstmals.
So und jetzt habe ich den für mich schon komplizierten Code zwar verstanden, nur funkt. es bei mir nicht..!
Aber vorerst, wollte ich dich etwas wegen der Namensbennenug fragen..
So wie ich es verstanden habe, sollte der Name nicht 'labeltext' heissen, da ich im UserControl ein Event definiere, das von anderen Forms, UserControls, usw unterschiedlich 'genutzt'(fällt kein besseres wort ein) werden kann.
Ich MUSS aber nicht einen anderen namen benutzen, nur weil UserControl nicht weiss, was ich mit diesem event machen werde, ist es besser ein neutraleren namen zu verwenden...so meinst du es oder..???Jetzt zum meinem eigentlichen prob...
...Ms Studio zeigt mir folgenden Fehler bei der Startform..:Fehler: "usercontrol.UserControl1.labeltextEventArgs" ist "Typ" und im angegebenen Kontext nicht gültig.
Hier nochmal die beiden Codes, vielleicht habe ich da wieder was falsch gemacht..:
//UserControl public event EventHandler<labeltextEventArgs> Write_Text; protected virtual void OnWrite_Text(string textReceived) { EventHandler<labeltextEventArgs> label_event = this.Write_Text; if (label_event != null) { label_event(this, new labeltextEventArgs(textReceived)); } } public class labeltextEventArgs : System.EventArgs { private readonly string text; public labeltextEventArgs(string text) : base() { this.text = text; } public string Text { get { return this.text; } } } private void button1_Click(object sender, EventArgs e) { OnWrite_Text("was"); }
und in der Startform..:
public partial class Form1 : Form { UserControl1 usr = new UserControl1(); public Form1() { InitializeComponent(); // Hier ist der Fehler UserControl1.labeltextEventArgs += labeltextEventArgs_event; } private void Form1_Load(object sender, EventArgs e) { splitContainer1.Panel2.Controls.Add(usr); } private void labeltextEventArgs_event(object sender, labeltextEventArgs e) { label1.Text = e.Text; } }
-
Du mußt die Event-Variable angeben (nicht den Typ):
UserControl1.Write_Text += labeltextEventArgs_event;
Und wegen der Namensbenennung: genau so meinte ich das -)
-
Ahh, ok...jetzt gehts..!
DANKE dir herzlich für deine Hilfe...!!!!!