Autor |
Beitrag |
Christoph1972
      
Beiträge: 690
Erhaltene Danke: 16
VS2015 Pro / C# & VB.Net
|
Verfasst: Mo 01.12.08 18:57
Hallo zusammen,
Ich bin zu blöd zum casten. Und zwar möchte ich eine Listbox via OwnerDraw zeichnen. Die ListBox ist an eine DB gebunden. In der DB gibt es ein Boolean-Feld. Wenn dieses Feld auf true steht möchte ich das der Text für diesen Datensatz grau gezeichnet wird.
Mit VB.Net habe ich das bisher so gemacht, das funktioniert auch soweit ganz gut.
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| Private Sub ListBox1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem Dim lb As ListBox = CType(sender, ListBox) Dim dataItem As String = CType(lb.Items(e.Index), DataRowView)(lb.DisplayMember).ToString
e.DrawBackground()
Dim I As Integer Dim DR As DataRow For I = 0 To GSMDatabaseDataSet.Table.Rows.Count DR = GSMDatabaseDataSet.Tables(0).Rows(e.Index) If DR("CA_ID").ToString.Contains(dataItem) Then If DR("Ready").ToString = "True" Then e.Graphics.DrawString(dataItem, lb.Font, Brushes.Gray, e.Bounds) Else e.Graphics.DrawString(dataItem, lb.Font, Brushes.Black, e.Bounds) End If End If Next End Sub |
So, nun sollte schon mal klar sein was ich vorhabe. Mein Problem ist nun, das ich das Casten in C# nicht gebacken kriege. Bisher bin ich soweit:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| void listBox1_DrawItem(object sender, DrawItemEventArgs e) { ListBox lb = (ListBox)sender as ListBox; string dataItem = (DataRowView)lb.Items[e.Index](lb.DisplayMember).ToString; e.DrawBackground();
foreach (DataRow DR in hLCDatenbankDataSet.Tables["Stammdaten"].Rows) { if (DR["C_ID"].ToString().Contains(dataItem)) { if (Convert.ToBoolean(DR["JobReady"]) == true) { e.Graphics.DrawString(dataItem, lb.Font, Brushes.Gray, e.Bounds); } else { e.Graphics.DrawString(dataItem, lb.Font, Brushes.Black, e.Bounds); } } } } |
Ich bekomme diese Zeile : Dim dataItem As String = CType(lb.Items(e.Index), DataRowView)(lb.DisplayMember).ToString nicht übersetzt.
Könntet ihr mir bitte behilflich sein, damit ich heute Nacht schlafen kann  Ich würde mich auch gerne zu diesem Thema weiterbilden, aber ich habe nichts zu dem Thema in meinen Büchern stehen und im Netzt habe ich bisher auch nichts gefunden. Auch in VB.Net fand ich das schon zum Haareraufen, daher muss ich jetzt was unternehmen!
Gruß
Christoph
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mo 01.12.08 19:09
Im Moment habe ich noch etwas anderes zu erledigen. Bis etwa 20 Uhr werde ich noch eine Antwort schreiben, sofern kein anderer schneller ist. Jürgen
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Mo 01.12.08 19:18
Probier mal das:
C#-Quelltext 1:
| string dataItem = ((DataRowView)lb.Items[e.Index]).DisplayMember.ToString(); |
|
|
Christoph1972 
      
Beiträge: 690
Erhaltene Danke: 16
VS2015 Pro / C# & VB.Net
|
Verfasst: Mo 01.12.08 19:45
Hi
Vielen Dank schon mal! Aber das funktioniert noch nicht. "DataRow" enthält keine Definition für Display member. Ich glaube das hatte ich heute auch schon mal so versucht. Hm, ist das verhext.....
Gruß
Christoph
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Mo 01.12.08 19:55
C#-Quelltext 1:
| string dataItem = ((DataRowView)lb.Items[e.Index])[lb.DisplayMember].ToString(); |
sollte besser sein, kanns nur gerade nicht nachschauen, ob das so passt.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 01.12.08 20:02
So hätte ich es auch übersetzt, allerdings ist die gesamte Methode etwas merkwürdig.
Wie wär's damit?
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| void listBox1_DrawItem(object sender, DrawItemEventArgs e) { ListBox lb = (ListBox)sender as ListBox; var row = (DataRowView)lb.SelectedItem; var brush = (bool)lb.SelectedValue ? Brushes.Gray : Brushes.Black; e.DrawBackground(); e.Graphics.DrawString(row[lb.DisplayMember].ToString(), lb.Font, brush, e.Bounds); } |
_________________ >λ=
Zuletzt bearbeitet von Kha am Mo 01.12.08 21:08, insgesamt 1-mal bearbeitet
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mo 01.12.08 20:09
So, ich kann mal anfangen...
Mir gefällt das Vorgehen auch nicht (ebenso wie Sebastian). Das Konvertieren ToString solltest Du sowieso nur dann machen, wenn Du wirklich Strings vergleichen willst; in allen anderen Fällen wird das nur unübersichtlicher und fehleranfällig.
Wie werden die ListBox.Items eigentlich zugeordnet? Genauer: von welchem Typ sind die Items? Von welchem Typ sind die Spalten "C_ID" und "JobReady"? Vermutlich int und bool, oder? Dann sollten diese Typen auch bei den Prüfungen verwendet werden.
Übrigens, warum Sebastian ohne Schleife arbeitet: DrawItem wird immer für ein spezielles Item aufgerufen; es muss also nur dieses - erkenntlich an e.Index - geprüft und gezeichnet werden.
Jürgen
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 01.12.08 21:11
JüTho hat folgendes geschrieben : | Genauer: von welchem Typ sind die Items? Von welchem Typ sind die Spalten "C_ID" und "JobReady"? Vermutlich int und bool, oder? |
Das erinnert mich daran, dass ich noch ein paar Casts einfügen sollte *g* ... verbessert
Zitat: | Übrigens, warum Sebastian ohne Schleife arbeitet: DrawItem wird immer für ein spezielles Item aufgerufen; es muss also nur dieses - erkenntlich an e.Index - geprüft und gezeichnet werden. |
Bei ihm wird auch nur ein einzelnes Item gezeichnet; die Schleife diente dazu, zur DataRowView die passende DataRow zu finden, aber frag mich nicht nach dem Sinn  .
_________________ >λ=
|
|
Christoph1972 
      
Beiträge: 690
Erhaltene Danke: 16
VS2015 Pro / C# & VB.Net
|
Verfasst: Mo 01.12.08 23:31
Super Jungs! Dank euch kann ich heute Nacht vorzüglich schlafen
Bei ihm wird auch nur ein einzelnes Item gezeichnet; die Schleife diente dazu, zur DataRowView die passende DataRow zu finden, aber frag mich nicht nach dem Sinn
Das mache ich, damit man gleich in der ListBox sehen kann welche Jobs abgearbeitet sind. Wenn ein Job erledigt ist, wird ein Häckchen gesetzt "Job Ready" und das Listbox Item wird grau. Übersicht schaffen, das ist der Grund.
Wo kann ich denn noch was über Casting nachlesen? Das Problem ist jetzt zwar behoben, aber es wird nicht lange dauern, dann falle ich wieder auf die Nase. Eine Liste mit Beispielen + Erkärung könnte mir schon sehr helfen. Der Winter ist immer eine gute Zeit sich mit neuen Dingen zu beschäftigen, wie z.B. Casting oder der Umstieg von VB.Net nach C#
Gruß
Christoph
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Di 02.12.08 10:51
Kha hat folgendes geschrieben : | Bei ihm wird auch nur ein einzelnes Item gezeichnet; die Schleife diente dazu, zur DataRowView die passende DataRow zu finden |
Stimmt, habe ich nicht richtig beachtet.
Einige Beispiele zum Casten (übernommen aus den obigen Code-Auszügen) mit Erläuterungen:
C#-Quelltext 1: 2:
| ListBox lb = (ListBox)sender as ListBox; |
Das ist doppelt gemoppelt. Es genügt eines von beiden:
C#-Quelltext 1: 2: 3: 4: 5:
| ListBox lb = sender as ListBox; if (lb != null) ListBox lb = (ListBox)sender; |
Die erste Variante ist hier besser, weil sie null zurückliefert, wenn sender wider Erwarten keine ListBox ist; die zweite Variante führt zu einer Exception.
Bei Feldinhalten innerhalb einer DataRow (oder DataRowView oder DataGridViewRow) ist dieses üblich:
C#-Quelltext 1: 2:
| int id = (int)DR["C_ID"]; bool OK = (bool)DR["JobReady"]; |
Dies wird vor allem deshalb gern genommen (anders als meine Erläuterung gerade eben), weil der Programmierer bei einer DataRow weiß, welchen Typ der Feldinhalt hat.
Diese Variante ist auch geeignet, weil sie direkt in eine Anweisung eingebunden werden kann, wie bei Sebastians Festlegung von brush:
C#-Quelltext 1: 2:
| var brush = (bool)lb.SelectedValue ? Brushes.Gray : Brushes.Black; |
Als weitere Erläuterung kenne ich Casten aber richtig: Begriffe wie Cast / is / as.
Viel Erfolg weiterhin! Jürgen
|
|
Christoph1972 
      
Beiträge: 690
Erhaltene Danke: 16
VS2015 Pro / C# & VB.Net
|
Verfasst: Di 02.12.08 17:49
Vielen Dank für die Antworten und den Link! Wirklich super!!
Ich wollte noch bemerken, das der letzte Versuch von gestern so ausgesehen hat :
string dataItem = ((DataRowView)lb.Items[e.Index])[lb.DisplayMember].ToString;
Gruß
Christoph
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 02.12.08 19:46
Off-Topic: IMHO ist die Syntax zum Casten in C-Sprachen absolut bescheuert. Die Pascal-Art var lb := ListBox(sender); ist viel lesbarer.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Christoph1972 
      
Beiträge: 690
Erhaltene Danke: 16
VS2015 Pro / C# & VB.Net
|
Verfasst: Di 02.12.08 21:39
Off-Topic: Ja das sehe ich auch so. Unter VB.Net ist es auch deutlich lesbarer :
C#-Quelltext 1:
| Dim lb As ListBox = CType(sender, ListBox) |
Man erhält sogar unterstützung durch die IDE. Da ist VB.Net etwas besser als C#. Unter C# ist die(der?) Syntax irgendwie zusammengeklatscht und wirkt nicht gerade Net konform.
Gruß
Christoph
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Mi 03.12.08 12:21
Christian S. hat folgendes geschrieben : | Off-Topic: IMHO ist die Syntax zum Casten in C-Sprachen absolut bescheuert. Die Pascal-Art var lb := ListBox(sender); ist viel lesbarer. |
Deswegen gibt es in C# ja auch noch var lb = (sender as ListBox);
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mi 03.12.08 12:59
Macht IIRC nicht dasselbe. Der Cast mit "as" wirft eine Exception, wenn's nicht passt, der "normale" Cast ergibt einfach nur null.
Siehe Jürgens Antwort.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Zuletzt bearbeitet von Christian S. am Mi 03.12.08 13:17, insgesamt 1-mal bearbeitet
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mi 03.12.08 13:09
Christian S. hat folgendes geschrieben : | Der Cast mit "as" wirft eine Exception, wenn's nicht passt, der "normale" Cast ergibt einfach nur null. |
Falsch, genau umgekehrt!
Und dass es in C# beide Varianten gibt, habe ich ja oben schon mit Erläuterung gesagt.
Jürgen
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 05.12.08 00:17
JüTho hat folgendes geschrieben : | C#-Quelltext 1: 2:
| ListBox lb = (ListBox)sender as ListBox; | |
Zwar nicht von mir sondern nur ungeprüft übernommen, trotzdem peinlich  .
Christian S. hat folgendes geschrieben : | Die Pascal-Art var lb := ListBox(sender); ist viel lesbarer. |
Lesbarer auf jeden Fall, aber ich weiß nicht, was ich von solchen Pseudo-Funktionen halten soll  . Gut, höchstens Anfänger werden sich dabei fragen, ob Oxygene nun doch globale Funktionen besitzt, aber der Unterschied zwischen Point(x) und new Point(x, y) verschwimmt dadurch auch ein wenig.
Wahrscheinlich also doch lieber ein binärer Operator wie as, nur eben mit der richtigen Funktion  .
F# 1:
| let lb = sender :?> ListBox |
Christoph1972 hat folgendes geschrieben : | Da ist VB.Net etwas besser als C#. Unter C# ist die(der?) Syntax irgendwie zusammengeklatscht und wirkt nicht gerade Net konform. |
Tsts, das solltest du Hejlsberg lieber nicht ins Gesicht sagen. Und wie eine Syntax überhaupt .Net-unkonform sein kann, übersteigt zu dieser späten Stunde meine Vorstellungskraft  .
OT im OT:
UGrohne hat folgendes geschrieben : | Deswegen gibt es in C# ja auch noch var lb = (sender as ListBox); |
Wäre eigentlich auch mal ein schönes Language-Feature: Mehrere Operatoren-Sätze für den jeweiligen persönlichen Geschmack  .
_________________ >λ=
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Fr 05.12.08 00:41
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 05.12.08 13:27
Zur Verteidigung muss ich aber mal etwas weiter ausholen: Im Gegensatz zu den meisten imperativen Sprachen benutzt OCaml einen eigenen Operator für Upcasts, nämlich x :> T. Der ist doch hoffentlich noch schön bildhaft, jedenfalls eher als irgendein (T)x  (wird aber in F# kaum gebraucht). Das Fragezeichen beim Downcast symbolisiert nun einfach die Tatsache, dass er im Gegensatz zum Upcast auch fehlschlagen kann. Vielleicht nicht gerade aussprech-freundlich, zum Ausgleich darf man aber insgesamt reichlich an runden und geschweiften Klammern sparen  .
Gestern ganz vergessen:
JüTho hat folgendes geschrieben : | Die erste Variante ist hier besser, weil sie null zurückliefert, wenn sender wider Erwarten keine ListBox ist; die zweite Variante führt zu einer Exception. |
Darüber lässt sich streiten (wie über vieles  ). Die Methode dient dazu, Items einer gegebenen ListBox zu zeichnen, für andere Klassen ist ihr Verhalten nicht definiert und sie auch gar nicht vorgesehen. Deshalb will ich eine Fehlermeldung beim Testen sehen, wenn solch ein undefiniertes Ereignis eintritt.
_________________ >λ=
|
|