Sender Tag auswerten
-
Hi,
ich habe eine Form mit 9 Labels (lbl0 - lbl8).
Alle haben die gleiche Click-Ereignissmethode,
allerdings sind die Tag Eigenschaften gleich wie ihre Namen durchnummeriert.
Wenn ich nun auf die Tag Eigenschaft über sender zugreifen und diese nach int konvertieren will,Convert.ToInt32((Label)sender)
meldet der Kompiler keinen Fehler.
Aber bei der Ausführung gibt es folgende Ausnahme:
System.InvalidCastException wurde nicht behandelt.Kann mir das bitte jemand erklären?
Vielen Dank im Voraus
Hobby Programmierer
-
So versuchst du aber das Label in ein int umzuwandeln, nicht den Tag.
Meinst doch wohl eherLabel label = (Label)sender; // noch besser mittels "as Label"!!! int tag = (int)label.Tag;
(und vergiß die Convert-Methoden - diese sind eher für Code-Generatoren geeignet als für saubere objektorientierte Programmierung)
-
Danke, hast mir sehr geholfen.
Hatte in meinem ersten Beitrag eigentlich gemeint:
[cs]Convert.ToInt32(((Label)sender).Tag)[cs]Aber eine Frage hätte ich noch:
Geht das was du mir geschrieben hast auch in einer Anweisung?Danke
-
sry für Doppelpost
aber es kommt in deiner zweiten Zeile die selbe Fehlermeldung.
Habe vorher es nicht richtig getestet.
-
Schreibst Du strings in Tag?
-
Hallo Hobby_Programmierer,
hast du die Tags über den PropertyEditor (Eigenschaften-Fenster) eingegeben? Dann sind es Strings (so wie µ schon gefragt hat), auch wenn du dort Zahlen eingibst.
Du müßtest dann mittels TryParse die Zahl auslesen:Label label = (Label)sender; // noch besser mittels "as Label"!!! int tag; string sTag = label.Tag as string; if (sTag != null) // Abfrage, ob auch wirklich ein String dort drin steht { if (Int32.TryParse(sTag, out tag)) { // nun steht in 'tag' die korrekte Zahl } else { // Fehler beim Parsen (d.h. keine korrekte Zahl, z.B. Leerstring) } }
Ansonsten laß dir einfach mal im Debugger den Typ von 'label.Tag' anzeigen.
-
"Tag" ist laus MSDN von der "Control" Basisklasse. Wozu also nach Label casten wenn man direkt eine "generischere" Methode machen kann.
public int GetIntegerFromControlTag(object sender, int fallback) { var control = sender as Control; if (control == null) return fallback; int converted; return int.TryParse(control.Tag, NumberStyles.Integer, new CultureInfo(1033), out converted) ? converted : fallback; }
Das kann man dann auch schön Testen ^^
[TestMethod] public void GetIntegerFromControlTag_ObjectIsNotAControl_ReturnsFallback() { var target = new DemoClass(); var actual = target.GetIntegerFromControlTag("string", 7); Assert.IsTrue(7, actual); } [TestMethod] public void GetIntegerFromControlTag_ControlTagIsAString_ReturnsFallback() { var target = new DemoClass(); var control = new Label {Tag = "string"}; var actual = target.GetIntegerFromControlTag(control, 7); Assert.IsTrue(7, actual); } [TestMethod] public void GetIntegerFromControlTag_ControlTagIsAnInteger_ReturnsTagInteger() { var target = new DemoClass(); var control = new Label {Tag = 1}; var actual = target.GetIntegerFromControlTag(control, 7); Assert.IsTrue(1, actual); }
(alles hier im Forum getippt, muss nicht funktionieren)
-
Ich persönlich finde es äußert fragwürdig in der Tag-Eigenschaft was zu speichern.
-
Vielen Dank an Th69, denn ich habe es jetzt ähnlich wie er gelöst.
Label label = sender as Label; int Tag; string sTag = label.Tag as string; int32.TryParse(sTag, out Tag);
Firefighter schrieb:
Ich persönlich finde es äußert fragwürdig in der Tag-Eigenschaft was zu speichern.
Warum? Wie würdest du es machen wenn du eine Ereignissmethode für verschiedene Steuerelemente hättest, die Ereignissmethode aber mit if änderbar sein muss?
-
Warum?
- Weil ich der Meinung bin das diese umhercasterei recht gefährlich ist.
- Weil man mal schnell was vergessen kann wenn sich an den Tags was ändert oder wenn neue Labels hinzukommen.Wie würde ich es machen:
- Naja, du könntest es über Bindings machen.
- Oder du könntest die Labels im Code erzeugen, über eine Schleife und im Code anonyme Eventhandler anlegen und mit den erzeugten Indizies arbeiten.Da wir aber nicht wissen was du vorhast, können meine Ideen genauso gut fürn Müll sein
-
Hobby_Programmierer schrieb:
Vielen Dank an Th69, denn ich habe es jetzt ähnlich wie er gelöst.
Label label = sender as Label; int Tag; string sTag = label.Tag as string; int32.TryParse(sTag, out Tag);
Wenn du schon mit "as" arbeitest, prüfe auch auf null, sonst hat das ganze keinen Sinn.
Wenn du es nicht machst, knallt es bei der ersten Verwendung direkt mit einer NullReferenceException weg.Nur die Verwendung von "as" macht es nicht auf Magische Weise sicher.
Unabhängig davon finde ich die Verwendung des Tags auch sehr Fragwürdig.
Erstell doch eine Methode pro Steuerelement, die rufen dann die Eigentliche Methode mit einem Parameter auf.
Dadurch entkoppelst du auch die UI von der Logik etwas.
-
@David W
bei as auf null zu prüfen ist sinnlos, da ich die Tags im Designer eingebe und im Programm nie ändere@David W und Firefighter
Ich programmiere ein Tic Tac Toe. Da jedesmal etwas ähnliches passieren muss, aber doch nicht gleich (wie muss der Computer reagieren...) sind mir die Tags angenehm.PS: Ich zwinge niemanden auch Tags zu benuzten!
-
Hobby_Programmierer schrieb:
@David W
bei as auf null zu prüfen ist sinnlos, da ich die Tags im Designer eingebe und im Programm nie ändereDann brauchst du es auch nicht mit "as" casten sondern kannst hart casten wie du es zuvor hattest.
Dann sparst du dir den Runtime Typecheck.
-
Hobby_Programmierer schrieb:
@David W
bei as auf null zu prüfen ist sinnlos, da ich die Tags im Designer eingebe und im Programm nie ändere@David W und Firefighter
Ich programmiere ein Tic Tac Toe. Da jedesmal etwas ähnliches passieren muss, aber doch nicht gleich (wie muss der Computer reagieren...) sind mir die Tags angenehm.PS: Ich zwinge niemanden auch Tags zu benuzten!
Ok jedem das seine
-
Tja, wir als Profi-Progger würden sowas nie benutzen.
-
Es ist eher eine Frage des Stils und was man für Ansprüche an sich selber hat.
Ein guter Stil ist es mMn nicht. Projekte die ich selber schreibe sollen meinen eigenen Ansprüchen genügen (was sie allerdings selten schaffen, da ich sehr selbstkritisch bin).
-
Firefighter schrieb:
Ich persönlich finde es äußert fragwürdig in der Tag-Eigenschaft was zu speichern.
Dem stimme ich zu.
Warum verarbeitest Du nicht den Namen der 9 Labels.
Ich sehe da keinen Sinn "Tag" zu verarbeiten.
Label label = sender as Label; MessageBox.Show(label.Name);
Die Abfrage welches Label geklickt wurde, machst Du über eine if-Anweisung oder einer switch-case-Anweisung...
Label label = sender as Label; switch (label.Name) { case "label1": MessageBox.Show("1"); break; case "label2": MessageBox.Show("2"); break; default: MessageBox.Show("3"); break; }
-
var allLabels = { label1, label2, label3, ..., ... }; for(int i = 0; i < allLabels.Count; ++i) { int labelIndex = i; allLabels[i].OnClick = (eventArgs) => ProcessLabelClick(labelIndex); }
-
Sorry kleinere Fehler im vorherigen Beispiel. So könnte man mit einer Funktion alle Labels verarbeiten anhand des Index.
void ProcessLabelClick(int i) { MessageBox.Show(i.ToString()); } var allLabels = new List<Label> { label1, label2 }; for (int i = 0; i < allLabels.Count; ++i) { int labelIndex = i; allLabels[i].Click += (sender, eventArgs) => ProcessLabelClick(labelIndex); }
-
Mit einer normalen Klick Methode ginge es nach diesen Prinzip auch, da man den Sender dann mit IndexOf in der Liste suchen kann und dann den Index bekommt.