Laden...

Wie von einer Windows-Form auf die GUI-Elemente einer anderen Windows-Form zugreifen?

Erstellt von sharp vor 16 Jahren Letzter Beitrag vor 14 Jahren 37.928 Views
Information von herbivore vor 13 Jahren

Dies ist ein Thread, auf den aus der FAQ ([FAQ] Kommunikation von 2 Forms) verwiesen wird. Bitte keine weitere Diskussion, sondern nur wichtige Ergänzungen und diese bitte knapp und präzise. Vielen Dank!

S
sharp Themenstarter:in
91 Beiträge seit 2008
vor 16 Jahren
Wie von einer Windows-Form auf die GUI-Elemente einer anderen Windows-Form zugreifen?
//mein Hauptfenster
namespace WindowsApplicationZweiFormsTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void labelMainWindow_Click(object sender, EventArgs e)
        {
            labelMainWindow.Text = "LabelMain";
        }
    }
}

//mein 2tes Neben-Fenster
namespace WindowsApplicationZweiFormsTest
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void label2ndWindow_Click(object sender, EventArgs e)
        {
            //labelMainWindow.  //wie kann ich hier auf labelMainWindow zugreifen?
        }
    }
}

Wie kann ich in meinem Nebenfenster auf das label "labelMainWindow" vom Hauptfenster zugreifen? Denn diese label-Instanz ist nicht sichtbar, siehe auskommentierte Zeile:

//labelMainWindow.  //wie kann ich hier auf labelMainWindow zugreifen?

Dann hab ichs noch so versucht:

WindowsApplicationZweiFormsTest.Form1.labelMainWindow. //geht aber auch net, da er die Instanz labelMainWindow net sieht.
49.485 Beiträge seit 2005
vor 16 Jahren

Hallo sharp,

Wie von einer WIndow-Form auf die GUI-Elemente einer anderen Window-Form zugreifen?

gar nicht. Das ist auch nicht nötig. Ein Form sollte immer nur selber auf seine eigenen GUI Elemente zugreifen.

Wie kann ich in meinem Nebenfenster auf das label "labelMainWindow" vom Hauptfenster zugreifen?

Insbesondere sollte Form2 Form 1 überhaupt nicht kennen. Das ist auch alles nicht nötig.

Vergiss deinen bisherigen Ansatz. Das ist, sorry, Mist. Bessere Wege sind in [FAQ] Kommunikation von 2 Forms beschrieben.

herbivore

S
sharp Themenstarter:in
91 Beiträge seit 2008
vor 16 Jahren

Danke für den Link. Die eine Idee dort hat bei mir immerhin halbwegs geklappt. Habe nämlich eine neue Klasse mit einer static Veriable erstellt, deren Variable verändert und ausgelesen werden kann. Da meine beide Forms die Klasse sehen hat's auch fast funktioniert. Aber es hat nur "fast" geklappt, da ich ja so trotzdem nicht von Form2 aus die Form1-Elemente verändern kann, da diese von Form2 aus nicht sichtbar sind.

Die anderen Beispiele im Link fand ich etwas zu kompliziert und alle sehr unterschiedlich.
Weiss jemand welchen Code man hinzufügen muss, um von meinem Nebenfenster aus, eine Label-Komponente im Hauptfenster abzuändern?
(Paar wenige Zeilen Code müsten doch reichen?)

//Hauptfenster
namespace WindowsApplicationZweiFormsTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //öffnet das Nebenfenster
        private void button_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show();
        }
    }
}

//nebenfenster
namespace WindowsApplicationZweiFormsTest
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void buttonForm2_Click(object sender, EventArgs e)
        {
            string stringForm2 = textBox1.Text;
            //diesen String möchte ich auf das Label vom Hauptfenster schicken. Wie?
        }
    }
}
F
10.010 Beiträge seit 2004
vor 16 Jahren

Natürlich kann man in ein Haus auch hineinkommen, indem man eine Wand
einreisst, das macht es aber weder einfacher, noch ist es vernünftig.

Genauso ist es auch hier.

Bitte versuche die Grundlagen zu verstehen, und den von herbivore geposteten
Link zu benutzen.

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo sharp,

diesen String möchte ich auf das Label vom Hauptfenster schicken. Wie?

wie schon gesagt, eigentlich steht in [FAQ] Kommunikation von 2 Forms alles was du wissen musst.

Hier wäre es vermutlich am besten, einen eigenen Event zu definieren ([FAQ] Eigenen Event definieren), der von Form1 abonniert und von Form2 definiert und gefeuert wird. In eigenen EventArgs kannst du dann den String mitgeben.

herbivore

S
sharp Themenstarter:in
91 Beiträge seit 2008
vor 16 Jahren

Man o man, ich mach jetzt hier ewig dran rum.
Damit hat es endlich geklappt:
Von Form2 auf Form1 zugreifen.
mit den Code von "Rene Paschold".

++Hat der Code von Rene irgendwelche Nachteile gegenüber anderen Lösungen? ++(Gibt ja so viele andere Lösungsansätze auf dem Link...!)
Aber ich muss zuvor das WinForm-Steuerelement auf das ich zugreifen möchte von private auf public abändern!
Mit anderen Lösungsansätzen müsste man auch den Modifier zuvor auf public abändern?

 private void buttonForm2_Click(object sender, EventArgs e)
        {
            string stringForm2 = textBox1.Text; //diesen String möchte ich auf das Label vom Hauptfenster schicken. Wie?
            this._frm1.labelMainWindow.Text = stringForm2; //Yippie, jetzt klappts
        } 

Danke für deinen Event-Link herbivore, werd ich mir anschauen.

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo sharp,

die Lösung ist - leider - sehr schlecht. Sie verstößt gleich gegen beide Forderungen, die ich aufgestellt habe: Ein Form soll nicht auf die Controls eines anderen zugreifen und Form2 soll Form1 nicht kennen.

Gewöhne dir so schlechten Stil besser erst gar nicht an.

Einen besseren Vorschlag habe ich ja schon gemacht.

herbivore

S
sharp Themenstarter:in
91 Beiträge seit 2008
vor 16 Jahren

Hier wäre es vermutlich am besten, einen eigenen Event zu definieren ( [FAQ] Eigenen Event definieren), der von Form1 abonniert und von Form2 definiert und gefeuert wird.

Zwar hab ich noch keinen eigenen benutzerdefinierten Event. Aber der Event "ThisMyEvent" wird jetzt doch immerhin von Form2 definiert und gefeuert?

Was bedeutet "Event der von Form1 abonniert"? Ich meine, wie abonniert man? 🙁Bitte am besten ein Codebeispiel.

//nebenfenster (form2):
namespace WindowsApplicationZweiFormsTest
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
        
        private void buttonForm2_Click(object sender, EventArgs e)
        {            
            buttonForm2.MouseClick += new MouseEventHandler(ThisMyEvent);
        }

        public static void ThisMyEvent(Object objSender, EventArgs ea)
        {
            Console.WriteLine("ThisMyEvent (" + objSender + ", "+ ea + ")");
        }
    }
}
49.485 Beiträge seit 2005
vor 16 Jahren

Hallo sharp,

abonnieren = einen EventHandler registrieren, mit +=

herbivore

C
489 Beiträge seit 2007
vor 16 Jahren

Hallo

Ganz ehrlich: Ich habe auch nicht recht verstanden, wie man eigenen benutzdefinierten Event in der einen Form abfeuert, so dass die anderen Form reagiert. Vielleicht hat da noch einmal jemand Code dazu.

chrische

U
1.688 Beiträge seit 2007
vor 16 Jahren

Hallo chrische5,

was genau hast Du nicht verstanden?

Gemeint ist:

  1. Form2 stellt ein Event zur Verfügung (public event...) - s. Doku
  2. Form1 "abonniert" das: form2.theEvent+=form1.theHandler
  3. Form2 löst das Event "intern" aus - genau nach Lehrbuch, äh Doku - damit wird automatisch der Handler in Form1 aufgerufen

Damit muss natürlich Form1 Form2 kennen, nicht aber umgekehrt.

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo chrische5,

der Code steht in [FAQ] Eigenen Event definieren.

herbivore

C
489 Beiträge seit 2007
vor 16 Jahren

Hallo

Mit diesen Events habe ich anscheind noch Grundlagen zu lernen. Ich muss mich jetzt noch einmal hinsetzen und mir das anschauen.

chrische

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo chrische5,

das setzen wir natürlich voraus. Die Links zu den entsprechenden Kapiteln in Openbook findest du ebenfalls in [FAQ] Eigenen Event definieren.

herbivore

C
489 Beiträge seit 2007
vor 16 Jahren

Hallo

  1. Form1 "abonniert" das: form2.theEvent+=form1.theHandler

Muss hier form2 nicht form1 kenn, um den Handler zu abonnieren?

chrische

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo chrische5,

nein, Form1 registriert ja den Handler für den Event von Form2.

Bevor du weiter fragst, setze erstmal deinen eigenen Vorschlag, dir die Grundlagen anzueignen, um. Dann ergibt sich die Antwort, wer wen kennen muss automatisch. Events sind ja gerade dazu da, diese Entkoppelung (also das Form2 Form1 nicht kennen muss) zu erreichen.

herbivore

C
489 Beiträge seit 2007
vor 16 Jahren

Hallo

Ich habe es geschafft.

Danke, wie immer.

chrische

S
sharp Themenstarter:in
91 Beiträge seit 2008
vor 16 Jahren

Ich habe es geschafft.

Falls du den Code noch hast, dann wärs toll wenn du den hier posten könntest. Ich checks nämlich mit den Events leider nicht. (oder mir alternativ eine perönliche Nachricht schicken wäre nett, ganz liebGuck)
Ansonsten werd ich aufgeben müssen. 🙁

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo sharp,

Ansonsten werd ich aufgeben müssen.

unterlasse bitte doch solche Sprüche. Entweder du meinst es ernst, dann können dich auch ein paar Schwierigkeiten nicht abhalten oder du meinst es nicht ernst, dann solltest du uns gar nicht erst in Anspruch nehmen. Wir möchten unsere Zeit sinnvoll investieren.

herbivore

C
489 Beiträge seit 2007
vor 16 Jahren

Hallo

Ich hoffe, dass man ich mich jetzt nicht unbeliebt mache, aber ich zeige trotzdem mal, wie ich es gemacht habe. Ich will es nicht per PM schicken, weil ja sonst nioemand anders was davon hat.

Form1 -> Form2

Form1 kennt Form2, weil es dieses aufruft udn erstellt. Eine Aktion in Form2 soll dazu führen, dass eine Funktion von Form1 ausgeführt wird:

Form2:


public delegate void DeleteImageHandler();

class form2
{
public event DeleteImageHandler DeleteImageEvent;
}

Form1:


form2.DeleteImageEvent += deineFunktion;

Ich hoffe, dass es jetzt bei dir klappt.

chrische

S
sharp Themenstarter:in
91 Beiträge seit 2008
vor 16 Jahren

Danke für den Codeschnipsel.
Ich check aber leider nicht wie das zu implementieren ist:

form2.DeleteImageEvent += deineFunktion; 

Und ich habe gesucht, in den Event-Links hier gabs aber kein einziges mal .DeleteImageEvent. Und im Internet gibt es ebenfalls KEIN einziges Resultat zu DeleteIMageEvent, ich kanns nicht glauben, google enttäuscht.

Form1:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.DeleteImageEvent += new EventHandler(ThisMyEvent); //wie geht das richtig? Compilerfehler: Cannot implicitly convert type 'System.EventHandler' to 'WindowsApplicationZweiFormsTest.DeleteImageHandler'.
//Ich habs auch mit anderen Dinge als "new EventHanfler" ausprobiert, aber immer Compilerfehler.
            form2.Show();
        }

        public static void ThisMyEvent(Object objSender, EventArgs ea)
        {
            Console.WriteLine("ThisMyEvent (" + objSender + ", " + ea + ")");
        }

    }
C
489 Beiträge seit 2007
vor 16 Jahren

Hallo

DeleteImageEvent ist ein von mir erstellter Event. Da findet du natürlich nichts im Internet. Schau dir mal genau, was ich gemacht habe. Du brauchst noch den delegaten.

chrische

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo sharp,

bitte lies die Verweise, die wir posten unbedingt gründlicher. Mindestens 50% deiner Nachfragen kommen, weil du es nicht getan hast. Wie das mit den Events geht, steht in [FAQ] Eigenen Event definieren. Wenn dir noch die Grundlagen fehlen, findest du gleich die Verweise auf die entsprechenden Kapitel im Openbook. Wir setzen diese Grundlagen voraus! Bitte beachte das! Bitte stelle keine weiteren Fragen, solange dir die Grundlagen fehlen. Siehe [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

herbivore

J
3 Beiträge seit 2007
vor 16 Jahren

Nochmal zum Ursprungspost: Man könnte auch einfach "labelMainWindow" public machen. Ist zwar ein schlechter Programmierstil, aber die schnellste Möglichkeit, wenn man es nur mal ausprobieren möchte.

95 Beiträge seit 2008
vor 14 Jahren

Ich habe jetzt schon oft gelesen: Die Forms dürfen sich gegenseitig nicht kennen, bzw. nur die eine die andere. Also in dem Buch, in dem ich mir die Grundlagen beigebracht habe, stand nichts darüber. Kann mir jemand eine Erklärung geben oder besteht dieser Thread hier schon? Habe ihn jedenfalls nicht gefunden.

Gruss Thomas

Gespräch zweier Informatiker:
"Wie ist denn das Wetter bei euch?"
"Caps Lock."
"Hä?"
"Na ja, Shift ohne Ende!"

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo laptor,

stell dir vor die Klasse List<T> würde die Klasse kennen, von der aus sie benutzt wird, und auf sie zugreifen. Nehmen wir an das wäre die Klasse Person. Das würde bedeuten, dass man die Klasse List<T> nicht benutzen könnte, wenn man keine Person hat. Die Klassen wären wechselseitig hart verdrahtet. Das ist natürlich Mist.

Daher sollte keine Klasse die Klasse kennen, von der sie benutzt wird, damit sie von jeder Klasse aus verwendet werden kann. Das hat nichts speziell mit Forms zu tun, gilt aber natürlich auch für Forms.

herbivore

1.002 Beiträge seit 2007
vor 14 Jahren

Hallo laptor,

Stichwort Kapselung von Daten.

Der große Vorteil besteht nun darin, dass das Objekt selbst dafür sorgen kann, dass die Konsistenz der Daten gewahrt bleibt. Falls zum Beispiel zwei Dateneinträge immer nur gemeinsam geändert werden dürfen, kann das Objekt dies sicherstellen, indem eine Änderung eines einzelnen Wertes gar nicht vorgesehen wird.

Ein weiterer Vorteil besteht darin, dass von einer Änderung der zugrunde liegenden Datenstruktur nur die Objekte betroffen sind, die diese Daten verwalten. Wenn jeder beliebig auf die Daten zugreifen könnte, wäre die Anzahl der Betroffenen in einem System möglicherweise sehr hoch, eine Anpassung entsprechend aufwändig.

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

95 Beiträge seit 2008
vor 14 Jahren

Hallo laptor,

stell dir vor die Klasse List<T> würde die Klasse kennen, von der aus sie benutzt wird, und auf sie zugreifen. Nehmen wir an das wäre die Klasse Person. Das würde bedeuten, dass man die Klasse List<T> nicht benutzen könnte, wenn man keine Person hat. Die Klassen wären wechselseitig hart verdrahtet. Das ist natürlich Mist.

Daher sollte keine Klasse die Klasse kennen, von der sie benutzt wird, damit sie von jeder Klasse aus verwendet werden kann. Das hat nichts speziell mit Forms zu tun, gilt aber natürlich auch für Forms.

herbivore

Ja das stimmt... Vielen Dank für die Antworten.

Gespräch zweier Informatiker:
"Wie ist denn das Wetter bei euch?"
"Caps Lock."
"Hä?"
"Na ja, Shift ohne Ende!"

5.299 Beiträge seit 2008
vor 14 Jahren

Ja, und inne Realität stolpert man dann über "Ausnahmen":
Jedes Control hat eine Parent-Property, und sogar eine .FindForm()-Methode, jeder TreeNode einen Parent, und sogar eine Treeview-Property, die Rows in typisierten Datasets haben typisierte Properties, die auf ihre ParentRows verweisen, und im entity-Framework stehen sich EntitySet<TChild> und EntityRef<TParent> gegenüber, und koppeln Parent und Child in Gegenseitigkeit.

scheinen mir Beispiele, die dem Grundatz_ "ein Objekt kennt seinen Owner nicht" _zuwiderlaufen.

Aber trotzdem kein schlechtes Design. Schon klar - die enge Kopplung von EntitySet<TChild> und EntityRef<TParent> schränkt die Flexiblität von TChild-Entities und TParent-Entities eklatant ein - aber das ist so gewollt, sonst könnte man eine Child-Entity in eine unpassende Parent-Entity hängen.
Dito für die TreeNodes: Die enge Kopplung ans Treeview ist nicht so schlimm, ohne Treeview macht ein Treenode eh nicht viel Sinn.

Der frühe Apfel fängt den Wurm.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo ErfinderDesRades,

scheinen mir Beispiele, die dem Grundatz "ein Objekt kennt seinen Owner nicht" zuwiderlaufen.

erstmal gibt es einen Unterschied zwischen "den Owner nicht kennen" und "die benutzenden Klasse nicht kennen". Das mit dem Owner kommt typischerweise bei Baumstrukturen vor. Und da ist es meisten auch ok, denn ...

Jedes Control hat eine Parent-Property

... das ist keine Ausnahme, denn die Property Parent ist in Control definiert und vom Typ Control. Da kennt sich nur die Klasse selbst, also kein Problem.

eder TreeNode einen Parent,

Auch das ist keine Ausnahme, weil Parent in TreeNode definiert und vom Typ TreeNode ist.

und sogar eine Treeview-Property

Das ist zwar eine Ausnahme, aber die Klassen TreeNode und TreeView gehören ohnehin so eng zueinander, dass sie nicht sinnvoll alleine verwendet werden können. Und das schreibst du ja am Ende auch selbst.

Fazit: Einige der genannten Fälle sind keine Ausnahmen und in den Fällen, in denen eine echte Ausnahme besteht, gibt es immer gute Gründe dafür. Das ändert also alles nichts am Grundsatz.

herbivore