Autor Beitrag
Christoph1972
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 690
Erhaltene Danke: 16


VS2015 Pro / C# & VB.Net
BeitragVerfasst: 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.
ausblenden 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:
ausblenden 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; //hier hänge ich fest
  
 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 :hair: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 01.12.08 19:18 
Probier mal das:
ausblenden C#-Quelltext
1:
string dataItem = ((DataRowView)lb.Items[e.Index]).DisplayMember.ToString();					
Christoph1972 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 690
Erhaltene Danke: 16


VS2015 Pro / C# & VB.Net
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mo 01.12.08 19:55 
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: 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?
ausblenden 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; // vorausgesetzt ValueMember = "JobReady"
  
  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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 01.12.08 21:11 
user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
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 :zwinker: .

_________________
>λ=
Christoph1972 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 690
Erhaltene Danke: 16


VS2015 Pro / C# & VB.Net
BeitragVerfasst: Mo 01.12.08 23:31 
Super Jungs! Dank euch kann ich heute Nacht vorzüglich schlafen :wave:


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# :D

Gruß
Christoph
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: Di 02.12.08 10:51 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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:

ausblenden C#-Quelltext
1:
2:
//  von Sebastian (Kha)
ListBox lb = (ListBox)sender as ListBox;

Das ist doppelt gemoppelt. Es genügt eines von beiden:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
//  entweder:
ListBox lb = sender as ListBox;
if (lb != null//  usw.
//  oder:
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:
ausblenden 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:
ausblenden C#-Quelltext
1:
2:
var brush = (bool)lb.SelectedValue ? Brushes.Gray : Brushes.Black; 
// vorausgesetzt ValueMember = "JobReady", nämlich vom Typ bool


Als weitere Erläuterung kenne ich Casten aber richtig: Begriffe wie Cast / is / as.

Viel Erfolg weiterhin! Jürgen
Christoph1972 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 690
Erhaltene Danke: 16


VS2015 Pro / C# & VB.Net
BeitragVerfasst: 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; :nut:

Gruß
Christoph
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 690
Erhaltene Danke: 16


VS2015 Pro / C# & VB.Net
BeitragVerfasst: Di 02.12.08 21:39 
Off-Topic: Ja das sehe ich auch so. Unter VB.Net ist es auch deutlich lesbarer :

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mi 03.12.08 12:21 
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: Mi 03.12.08 13:09 
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 05.12.08 00:17 
user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden C#-Quelltext
1:
2:
//  von Sebastian (Kha)
ListBox lb = (ListBox)sender as ListBox;
Zwar nicht von mir sondern nur ungeprüft übernommen, trotzdem peinlich :angel: .

user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
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 ;) .
ausblenden F#
1:
let lb = sender :?> ListBox // _das_ ist doch mal ein ausdrucksstarker Operator					


user profile iconChristoph1972 hat folgendes geschrieben Zum zitierten Posting springen:
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 :nixweiss: .

OT im OT:
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
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 :D .

_________________
>λ=
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 05.12.08 00:41 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden F#
1:
let lb = sender :?> ListBox // _das_ ist doch mal ein ausdrucksstarker Operator					

:lol: Der Operator ist ja mal total bescheuert. Ich würde da direkt mal ()->!_! als nächsten Operator vorschlagen :D

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 05.12.08 13:27 
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
:lol:
:cry:

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 :D .

Gestern ganz vergessen:
user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
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.

_________________
>λ=