Entwickler-Ecke

WinForms - Event Handler? kenne den Namen nicht


Yumy - Di 23.12.08 18:21
Titel: Event Handler? kenne den Namen nicht
Hallo zusammen

Ich habe ein Problem was ich im Titel leider nicht wusste besser zu beschreiben.

Ich habe ein MenuStrip auf meiner Form.
Die einzelnen Buttons innerhalb des Strips werden durch eine Schleife erzeugt und bekommen
je nachdem was so in der Textdatei steht einen gekürzten Namen (es sind Pfade).
Zusätzlich speicher ich den gesamten Pfad jedes Buttons in einer Array List ab damit ich später
den Pfad öffnen kann wenn auf den Button geklickt wird.

Und da ist auch schon das Problem.
Ich muss den Code für das Ausführen des Pfades schreiben ohne zu wissen wie der Button heißt den ich soeben erzeugt habe.

Hier einmal der Code:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
 private void Form1_Load(object sender, EventArgs e)
        {

            for (int i = 0; i < 40; i++)
            {
                ArrayList pfadAL = new ArrayList();

                string text = (Return.ReadLine(GetProjectPath() + "pfad.txt", i + 1));
                
                if (Return.ReadLine(GetProjectPath() + "pfad.txt", i + 1) == "")
                {
                    break;
                }

                pfadAL.Add((Return.ReadLine(GetProjectPath() + "pfad.txt", i + 1)));
                string [] split = text.Split((new Char [] {'\\'}));
               
                toolstrip.DropDown.Items.Add(split[split.Count()-1]);


            }


Der ganze MenuStrip soll außerdem nicht zu viele Einträge bekommen, deswegen die Begrenzung.


Wäre echt froh wenn mir jemand weiterhelfen kann.
Stehe im moment echt auf dem Schlauch.


JüTho - Di 23.12.08 18:38

Hallo und :welcome:

zunächst einmal: ArrayList gehört in die Mottenkiste und sollte wie alle untypisierten Collections aus System.Collections nicht mehr benutzt werden. Verwende stattdessen List<T> und alle anderen typisierten Collections aus System.Collections.Generic; in Deinem Fall passt natürlich List<string>.

Verstehe ich es richtig, dass Du den letzten Bestandteil des Pfads als Beschriftung des Buttons verwenden willst? Dann nimm das doch als Namen. Oder (falls Du Bedenken wegen Doubletten hast) trage als ToolStripButton.Tag den vollständigen Pfad ein; den kannst Du später wieder auslesen.

Der sender des dazugehörigen EventHandler dürfte der ToolStripButton sein; dann kannst Du es etwa so auslesen (aus der SDK-Doku/MSDN übernommen):

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
public void changeDirectionButton_Click(object sender, EventArgs e)
{
    ToolStripItem item = (ToolStripItem)sender;
    string path = item.Tag as string;
    //  Sicherheitsprüfung
    if (! String.IsNullOrEmpty(path) ) {
       //  mach was
    }
}


Noch ein paar Hinweise: Der Pfad kann mit Path.GetDirectoryName herausgeholt werden. Der letzte Bestandteil ist besser mit String.LastIndexOf() und String.Substring() zu holen; das spart das Umspeichern über String.Split und ein String-Array. Namen von Klassen und Objekten, die wie Schlüsselwörter heißen, sind zumindest sehr gefährlich - hier Return und text; vermeide lieber solche Bezeichner, auch wenn der Compiler noch nicht meckert.

Viel Erfolg und Frohe Weihnachten! Jürgen


Yumy - Di 23.12.08 18:54

Vielen dank für deine schnelle Antwort.
Finde es gut das du mir auch sagst was nicht so "elegant" gelöst ist :)
Bin halt noch relativ frisch in dem Bereich.

Aber eine Frage habe ich noch:

Mir ist noch nicht ganz klar wie ich innerhalb der Schleife dem 1-... Button der erzeugt wird einen Namen zuweise.
Erzeugen tu ich sie mit diesem Schnipsel:
toolstrip.DropDown.Items.Add(split[split.Count()-1]);
Allerdings habe ich so nur die Möglichkeit den Text des Buttons festzulegen oder liege ich da falsch?


JüTho - Di 23.12.08 19:13

Hallo,

Du solltest Dir schnell angewöhnen, in der SDK-Doku/MSDN nachzuschlagen; für viele Methoden (auch Konstruktoren) gibt es Überladungen, und unter "Alle Member" gibt es Erläuterungen für Eigenschaften und Methoden.

Konkret geht es z.B. so (nur so hingeschrieben als Anhaltspunkt, kein exakter Code):

C#-Quelltext
1:
2:
3:
4:
5:
ToolStripButton item = new ToolStripButton("Beschriftung");
item.Name = "Name";
item.Click += EventHandler(was_auch_immer);
item.Tag = "voller Name";
toolstrip.DropDown.Items.Add(item);

Jürgen


Yumy - Mi 24.12.08 16:40

Hallo,

ich habe heute noch ein wenig rumprobiert.
Das erstellen der Buttons und das Namen vergeben klappt auch wunderbar:


C#-Quelltext
1:
2:
3:
4:
ToolStripButton item = new ToolStripButton(split[split.Count() - 1]);
item.Name = "tsbutton" + i;
item.Tag = (Return.ReadLine(GetProjectPath() + "pfad.txt", i + 1));
toolstrip.DropDown.Items.Add(split[split.Count()-1]);

Allerdings wird in der Dokumentation immer nur auf fälle eingegangen wo die
Buttons vorher im Code erzeugt wurden.

Bsp:

C#-Quelltext
1:
  menuItem1.Click += new System.EventHandler(this.menuItem1_Click);                    


Ich erzeuge sie allerdings erst beim starten.
Bsp:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
item.Click += new EventHandler(tsbutton1ToolStripMenuItem_Click);

 private void tsbutton1ToolStripMenuItem_Click(object sender, System.EventArgs e)
        {       
           OpenFileDialog fd = new OpenFileDialog();
                fd.DefaultExt = "*.*";
           fd.ShowDialog();
        }


tsbutton1 würde der erste button heißen der in der Schleife erstellt wird.
Allerdings scheint es so nicht zu funktionieren.
Was mache ich falsch ?

MFG


JüTho - Mi 24.12.08 17:12

Hallo,

in meinem vorigen Beispiel hatte ich sofort item.Click einbezogen. Nach Deinen Code-Auszügen kommt das erst "irgendwann", oder? Warum?

Die Definition für dieses ItemClick ist doch im Code der Klasse enthalten, oder? Dann kann dieser EventHandler auch sofort bei seiner Erzeugung registriert werden.

Zitat:
Allerdings scheint es so nicht zu funktionieren.

Das ist normalerweise keine vernünftige Problembeschreibung. Die Hauptfrage lautet, ob der EventHandler zugewiesen wurde. Das kannst Du am schnellsten durch den Debugger mit einem Haltepunkt dort feststellen.

Gruß und Frohe Weihnachten! Jürgen


Yumy - Mi 24.12.08 17:43

Ich habe das

C#-Quelltext
1:
item.Click += new EventHandler(tsbutton1ToolStripMenuItem_Click);                    


nur für die Beschreibung rausgenommen um zu verdeutlichen das die anderen Schritte funktionieren.
In meinem Code ist es dann so wie du es aufgelistet hast.
Allerdings habe ich bis jetzt noch nie mit einem EventHandler gearbeitet.
In C# wird ja alles automatisch durch den Designer generiert.

Mein Problem ist jetzt einfach:

Ich habe mein MenuStrip, weise diesem die einzelnen Buttons zu (im moment sind das : "tsbutton1 - 5")
und schreibe den ganzen Pfad in den button Tag rein.

nun soll aber etwas passieren wenn ich auf den tsbutton1 klicke.
Wenn ich diese vorher festgelegt hätte würde ich es so schreiben:


C#-Quelltext
1:
2:
3:
4:
private void tsbutton1ToolStripMenuItem_Click(object sender, EventArgs e)
 {
     //Irgend eine Funktion
 }


Nun wäre sinnvoll zu wissen wo ich sehe ob der EventHandler eingetragen wurde.
Oder ob meine Schreibweise new EventHandler(tsbutton1ToolStripMenuItem_Click); und private void tsbutton1ToolStripMenuItem_Click(object sender, System.EventArgs e)
überhaupt so richtig ist.

Frohes Fest :)


JüTho - Mi 24.12.08 17:57

Hallo,

vereinfacht gesagt: Alles, was und wie in der Designer.cs steht, kannst Du auch manuell erledigen. Genauso wie dort ein EventHandler zugewiesen wird, kannst Du es ebenfalls machen (wie in meinem Code-Auszug). Wichtig ist zunächst, dass ein passender EventHandler existiert und verknüpft wurde; wo das geschieht, ist völlig unwichtig.

"passender" EventHandler heißt, dass die Parameter passen: Für ein Click-Ereignis genügt eine Standard-Methode mit sender und EventArgs; für ein MouseClick-Ereignis braucht man einen MouseEventHandler mit sender und MouseEventArgs (klar, man will ja wissen, welche Maus-Tasten gedrückt wurden) usw. Du musst also in der SDK-Doku/MSDN nachschauen, welche Art von EventHandler für ein bestimmtes Ereignis benötigt wird, eine passende Methode erstellen und beides verknüpfen.

Konkret: Deine Methode tsbutton1ToolStripMenuItem_Click passt wegen der EventArgs. Die Verknüpfung erfolgt durch "item.Click +="; unter NET 2.0 ff. kann man auch einfach schreiben:

C#-Quelltext
1:
item.Click += tsbutton1ToolStripMenuItem_Click;                    

Also sollten alle Voraussetzungen erfüllt sein. Warum es trotzdem nicht klappt? :(

Ein paar Hinweise mit Debugger hatte ich schon gegeben. Vielleicht ist das MenuItem auch auf Enabled = false eingestellt oder so etwas.

Gruß und Frohe Weihnachten! Jürgen