7.1k Aufrufe
Gefragt in Anwendungen(Java,C++...) von
Hallo zusammen! Ich habe ein kleines Problem und dazu eine Frage. Ich arbeite mit C# (bin noch Anfänger) und möchte folgendes tun:
In einer Form1 befindet sich eine Listbox1 und darin befinden sich 5 Einträge (X1, X2...,X5).
In einer Form2 befindet sich ein Label1.
Ich möchte nun erreichen, wenn ich z.B. auf den Eintrag X3 klicke, dass sich Form2 öffnet und im Label1 der Text X3 steht.
Ich habe das schon mit der Erstellung von neuen Instanzen versucht - klappt nicht. Auch der Versuch mit der Übergabe eines Parameters klappte nicht.
Kann mit bitte jemand behilflich sein und mir ein wenig auf die Sprünge helfen? Ich bin sicher das ist ganz einfach - nur ich komm nicht drauf. Danke schon mal im Voraus, Claudia.

26 Antworten

0 Punkte
Beantwortet von computerschrat Profi (32.2k Punkte)
Hallo Claudia,

ich versuche mal eine Schritt für Schritt Anleitung.

Basisvoraussetzung: Im Projekt sind bereits zwei Forms vorhanden, ich nenne sie Form1 und Form2
Wenn noch nicht vorhanden, dann musst Du im Projektmappen Explorer mit der rechten Maustaste auf die Wurzel des Projekts klicken (dort wo links neben dem Projektnamen C# in einem kleinen Kästchen steht) und dann wählen Hinzufügen -> Windows Form. Im nachfolgenden Dialog wählst Du wieder Windows Form und gibst dem Form unten noch einen Namen nach Wahl. Ich bleibe mal bei Form2.
Im Deklarationsteil von Form1 wird die neue Form2 angemeldet:

public partial class frm1 : Form
{

private Form2 _form2;

}


Der Teil mit public partial class ... existiert ja vermutlich ohnehin schon, da kommt nur die eine Zeile mit der private Deklaration für Form2 rein.

In der Funktion für das Form1-Load Ereignis fügst Du eine Zeile ein, die die Form2 dann erzeugt:

this._form2 = new Form2();


Ab jetzt kannst Du auf Elemente in Form2 zugreifen über

this._form2.SteuerelementName.Eigenschaft
Wenn Du also z.B. einen Button mit dem Namen btnKnopf im Form2 hast und möchtest den grün einfärben, dann geht das aus Form2 heraus über
this._form2.btnKnopf.BackColor=green;


Viel Erfolg

Gruß
computerschrat
0 Punkte
Beantwortet von computerschrat Profi (32.2k Punkte)
Ich muss mich nochmal melden,

Ich hatte vergessen, Form2 sichtbar zu machen.
zum Beispiel im onKlick Event für EintragX3, wo Du dem Label denText zuweist
this._form2.Visible = true;
this._form2.Label1.text= Text;


Gruß
computerschrat
0 Punkte
Beantwortet von
Hallo computerschrat,
danke für Deine schnelle Info, aber so funktioniert das leider nicht.
Vielleicht noch mal etwas anders formuliert: ich arbeite mit C# (bin noch Anfänger) und möchte folgendes tun:
In einer Form1 befindet sich eine Listbox1 und darin befinden sich 5 Einträge (X1, X2, X3, X4, X5).
In einer Form2 befindet sich ein Label1.
Ich möchte nun erreichen, wenn ich z.B. in der Form1 auf den Eintrag in der Listbox1 "X3" klicke (müßte nach meiner Meinung das SelectedIndexChanged_Event sein), dann soll Form2 geöffnet werden (also quasi eine neue Instanz von Form2) und im Label1 dieser Form2 soll der Text X3 stehen. Es sind dann also 2 Formulare oder Fenster geöffnet.
Wenn ich jetzt in der Form1 auf den Eintrag in der Listbox1 "X1" klicke, dann soll eine neue / weitere Form2 geöffnet werden (also quasi wieder eine neue Instanz von Form2) und im Label1 dieser Form2 soll dann der Text X1 stehen. Es sind dann also 3 Formulare oder Fenster geöffnet.
Ich habe Deine Version bzw. Deinen Vorschlag ausprobiert, aber funktioniert leider nicht, ich kann nicht auf die Elemente in Form2 zugreifen (ist ja nur das Label1 drin).
Wie schon gesagt, ich arbeite mit C# nicht mit VB!
Hast Du vielleicht noch andere Ideen? Wäre wirklich sehr nett. Danke im Voraus, Claudia.
0 Punkte
Beantwortet von computerschrat Profi (32.2k Punkte)
Hallo Claudia,

C# ist mir schon klar und mein Beispiel ist auch C#, in VB wäre die Benutzung der zweiten Form etwas weniger umständlich.

Wenn ich Dich richtig verstehe, möchtest Du bei jedem Klick in die Listbox eine neue Instanz von Form2 erzeugen? Sollen die anderen vorher erzeugten Instanzen dann offen bleiben oder werden die wieder geschlossen, so dass jeweils nur eine Instanz von Form2 existieren muss? Der Unterschied wäre, dass Du im einen Fall dynamisch neue Forms genereieren musst, die natürlich auch gleichzeitig sichtbar sein können. Im anderen Fall genügt eine Form2 und die wechselt jeweils zwischen sichtbar und unsichtbar hin und her. Das entspräche dann meinem Vorschlag.

Gruß
computerschrat
0 Punkte
Beantwortet von computerschrat Profi (32.2k Punkte)
Hallo Claudia,

jetzt habe ich mal probiert und "meine" Version mit einem Form2. in ein Projekt gegossen.
Der Code für beide Forms ist unten. Ich kann Dir auch das gesamte Projekt zukommen lassen. Dazu müsstest Du Dich hier bei Supportnet anmelden, dann kann ich Dir eine Nachricht schicken um Dir einen Account auf meinem FTP Server zu geben, dort kannst Du das Projekt dann laden. Diese Nachricht sollte nicht öffentlich für jedermann sichtbar sein.

Gruß
computerschrat

Form1:
###################
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ZweiForms
{
public partial class Form1 : Form
{
private Form2 _form2;
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
this._form2 = new Form2();
this._form2.Visible = true;
listBox1.Items.Add("Zeile1");
listBox1.Items.Add("Zeile2");
listBox1.Items.Add("Zeile3");
}

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string curItem = listBox1.SelectedItem.ToString();
int index = listBox1.FindString(curItem);

this._form2.Visible = true;
this._form2.label1.Text = curItem;
}

private void listBox1_SelectedIndexChanged()
{

}
}
}

###################

Form2:
###################
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ZweiForms
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}

private void Form2_Load(object sender, EventArgs e)
{

}
}
}

###################
0 Punkte
Beantwortet von
Hallo computerschrat,
danke erst einmal für Deine Info und Deine Mühe. Das ist die Fehlermeldung, die mir der Compiler beim Versuch das Programm laufen zu lassen ausgibt:

"Der Zugriff auf "ZweiForms.Form2.label1" ist aufgrund der Sicherheitsebene nicht möglich." Keine Ahnung was das bedeutet!

Zu Deiner Frage: die jeweiligen Instanzen von Form2 sollen offen bleiben, so dass ich dann zum Beispiel bei 5 Einträgen in der Listbox1 in Form1 auch 5 geöffnete Instanzen von Form2 hätte; nur das der Text im Label1 in Form2 jeweils ein anderer wäre.

Hast Du weitere Ideen? Wäre schön! Danke, C.
0 Punkte
Beantwortet von computerschrat Profi (32.2k Punkte)
Hallo Claudia,

die Fehlermeldung verschwindet, wenn Du im Form2.Designer.cs die Deklaration für das Label auf publick setzt:
public System.Windows.Forms.Label label1;



Um mehrere Instanzen der Form2 zu öffnen kannst Du folgendes tun.

public partial class Form1 : Form
{
private Form2 _form2;
private Form2 _form3;
private Form2 _form4;
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
this._form2 = new Form2();
this._form3 = new Form2();
this._form4 = new Form2();
listBox1.Items.Add("Zeile1");
listBox1.Items.Add("Zeile2");
listBox1.Items.Add("Zeile3");
}

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string curItem = listBox1.SelectedItem.ToString();
int index = listBox1.FindString(curItem);
switch (index)
{
case 0:
{
this._form2.Visible = true;
this._form2.label1.Text = curItem;
break;
}
case 1:
{
this._form3.Visible = true;
this._form3.label1.Text = curItem;
break;
}
case 2:
{
this._form4.Visible = true;
this._form4.label1.Text = curItem;
break;
}
default:
{
break;
}
}
}


Da sind mehrere Instanzen des Typs Form2 angelegt. Hier nur statisch, das musst Du noch dynamisieren, für den Fall, dass die Anzahl der Listbox-Einträge variabel ist. Du könntest z.B. die Switch-Case Anweisung dahingehend verändern, dass Du den Intex nimmst und prüfst, ob eine Instanz von Form2 mit dem Index SelectedItem der Listbox existiert. Wenn nicht, dann musst Du sie erzeugen. Wie man arrays of Forms erzeugen kann, findest Du hier:
stackoverflow.com/questions/8238756/c-sharp-using-an-array-of-forms-to-open-multiple-forms-at-the-same-time

Ausserdem musst Du noch dafür sorgen, dass die Instanzen wieder neu angelegt werden, falls sie jemand per Klick auf Schließen geschlossen haben sollte, oder aber Du nimmst den Schließen Button aus der Kopfzeile raus.

Gruß
computerschrat
0 Punkte
Beantwortet von
Hallo computerschrat,
danke vielmals für die HIlfe, vor allem für den Tip, im Formdesigner das Label1 in Form2 auf public zu setzen. Damit läuft es jetzt erst einmal so, wie ich es gewollt habe und es ist auch nicht sehr viel Quellcode übrig geblieben.
Nur mal zur Info:
###################Form1###################
public partial class Form1 : Form
{
public Form2 _form2;

public Form1()
{
InitializeComponent();
}

private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
this._form2 = new Form2();

string curItem = listBox1.SelectedItem.ToString();
int index = listBox1.FindString(curItem);

this._form2.label1.Text = curItem;
this._form2.Show();
}
}

###################Form2###################
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
}

Jetzt fehlt nur noch ein bischen Feinarbeit und das Ganze funktioniert richtig gut. Allerdings hätte ich noch eine letzte Frage: Wie kann ich am Besten das Click-Ereignis für Listbox1 in Form1 abfangen, wenn z.B. jemand auf die Listbox klickt, aber dabei keinen Eintrag trifft? Momentan stürzt das Programm ab und mit Ausnahmebehandlung komme ich dabei auch nicht weiter. Ich stelle mir dann eine MessageBox vor, in der geschrieben steht: "Bitte wählen Sie einen gültigen Listeneintrag aus!".
Hast Du vielleicht noch eine gute Idee? Danke und viele Grüße, Claudia.
0 Punkte
Beantwortet von computerschrat Profi (32.2k Punkte)
Hallo Claudia,

der Absturz erfolgt, weil listBox1.SelectedIndex nicht auf einen Wert in der ListBox zeigt. Damit schlägt der Zugriff auf den ListBox Eintrag natürlich fehl und löst einen Fehler aus.
Hier ist ein Vorschlag für die Fehlerbehandlung:

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int index;
string curItem;
curItem = "";
try
{
curItem = listBox1.SelectedItem.ToString();
index = listBox1.FindString(curItem);
}
catch
{
index = 99; // Hier gehts hin, wenn ein Fehler auftritt
curItem = "Fehler";
}

// Hier die Auswertung

}

in der Auswertung kannst Du dann im Falle des Fehlers eine Reaktion Deiner Wahl einbauen.

Gruß
computerschrat
0 Punkte
Beantwortet von
Hallo computerschrat,
danke für den Lösungsvorschlag, aber dieser Weg funktioniert leider nicht - hatte ich auch schon in Betracht gezogen.
Vielleicht war es von mir auch etwas schlecht beschrieben und deshalb noch mal in anderer Form:
Meine Listbox1 enthält im Augenblick 3 Einträge (X1, X2, X3) und die Listbox1 ist ca. 6cm hoch - also für drei Einträge viel zu groß, so dass also noch ungenutzter Platz vorhanden ist.
Wenn der Benutzer es nun eilig hat oder nicht richtig trifft oder mit der Naus abrutscht und genau auf diesen noch freien Platz klickt, wo ja kein Eintrag vorhanden ist, stürzt das Programm ab. Im weiteren Verlauf wird der noch freie Platz allerdingsauch noch belegt, so dass es dann zu keiner Fehlfunktion mehr kommen kann - die tritt also nur bei wenigen Einträgen ein.
Ich könnte jetzt die Listbox1 mit jedem neuen Eintrag in der Größe anpassen lassen, möchte ich aber nicht.
Statt dessen soll eine Meldung erscheinen, dass man einen gültigen Eintrag auswählen soll und das Programm soll nicht abstürzen.
Ungefähr verständlich erklärt? Danke für's Helfen, C.
...