Hintergrundfarben in Datagridview

  • VB.NET
  • .NET (FX) 4.0

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Atreju.AZ.

    Hintergrundfarben in Datagridview

    Hallo an alle,

    ich bin neu hier und möchte mich zunächst einmal vorstellen: Ich bin Holger und komme aus Rheinland-Pfalz. In den Neunzigern arbeitete ich bei einer Radiostation. Damals war ich der Meinung, dass das dort vorhandene Sendeautomationssystem viel zu umständlich und fehleranfällig war und begann, mit VB6 ein eigenes System zu entwickeln. Ohne dass dies jemals geplant war, lief das System bis Ende 1997 bei insgesamt 6 Stationen im kommerziellen Betrieb, bis ein Konkurrent das System Anfang 1998 vom Markt weggekauft hatte. Danach war ich für lange Zeit aus dem Programmieren raus. Bis ich 2017, inzwischen bei einer Fernsehstation angekommen, zum Spass mit einem templatebasierten Livegrafiksystem angefangen habe. Auch dieses ist inzwischen ungewollt mehrfach im produktiven Einsatz.

    Da ich ein lausiger Programmierer bin, verwendete ich zur Visualisierung von Daten wilde Konstruktionen aus Arrays und Listviews. Hier räume ich gerade auf und hierbei brauche ich Eure Hilfe.
    Einige Bereiche sind bereits auf typisierte Datasets umgestellt (Danke an @ErfinderDesRades), aber jetzt stehe ich auf dem Schlauch. Ihr lacht Euch jetzt tot...

    Ein Datenlieferant pusht alle paar Minuten viele XML-Dateien mehrerer Sportevents auf meinen Server. Weil ich von diesen Daten effektiv nur 5% benötige, parse ich die benötigten Daten in ein Dataset. Ich habe gelernt, dass man beim Datenhandling die Finger vom DGV lässt, also passiert das alles in der BS. In Abhängigkeit von den XML-Daten, Benutzereingaben und auch Timern muss der Ablaufplan, der von einem DGV angezeigt werden soll, ganz fürchterlich bunt werden. Manchmal ganze Rows, manchmal auch nur einzelne Cells. Dafür soll es eine Prozedur geben, die die Farben in Abhängigkeit von der Datenlage ins DGV pinselt. Bisher war das eine For-Each-Schleife durch das Listview, die nach Auswertung der Subitems die Backcolor-Eigenschaft gesetzt hat. Gruselig. Und jetzt? Ich stelle mir wieder eine entsprechende Schleife vor, vielleicht so etwas in der Art:

    VB.NET-Quellcode

    1. For Each row As DataRowView In AblaufBindingSource
    2. Dim col = DirectCast(DirectCast(row, DataRowView).Row, DataSetAblauf.AblaufRow)
    3. If col.Duration=... And ... col.RenderState=... Then 'hier die Auswertung der Datenlage
    4. 'und hier fehlt mir der Schritt von der BS ins DGV. Wie bekomme ich die Farben da rein? Für die gerade ausgewertete Row?
    5. Endif
    6. Next


    Ganz bestimmt habt ihr Ideen. Wahrscheinlich ist es ganz einfach, ich komme nur nicht drauf. Bitte nicht schlagen. Wie gesagt: Bin ein lausiger Programmierer...

    LG!
    Willkommen im Forum.

    Atreju.AZ schrieb:

    Bin ein lausiger Programmierer
    HA! Wenn Du es geschafft hast, das Beschriebene schon umzusetzen, braucht diese Selbsteinschätzung vielleicht die Bewertung von Außenstehenden. Ich glaube, Du stellst Dich (unabsichtlich) schlechter dar, als es den Tatsachen entspricht. Aber: Die Zeit wird's weisen. Und Dein Code wird's zeigen. Schau mer mal.
    Es kommt ein wenig drauf an. Wenn die Daten immer mehr werden, könntest Du die Kolorisierung machen, wenn Daten hinzukommen. Wenn die Einfärbung aber mit bestehenden Daten erfolgen soll, dann musst Du quasi herausfinden, wo sich die aktuelle DataRow des Schleifendurchgangs im DGV befindet. Wie ist denn die Situation?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hallo VaporiZed,

    vielen Dank für die freundlichen Worte. Ich denke, meine Stärken liegen in der Gestaltung eines UI, das die Benutzer auf Anhieb intuitiv bedienen können. Und natürlich macht der Code dahinter, was er soll. Aber frag nicht danach, wie... Ich lese hier seit vielen Jahren mit und sehe, wie elegant viele User hier coden können. Da bin ich sehr weit weg...

    Also: Der Ablaufplan wird von der Redaktion vorgegeben und kommt als Excel-Datei. Diese lese ich aus und die benötigten Columns werden in das Dataset geschrieben. In der Regel nicht mehr als 200-250 Zeilen. Das System parsed den Ablauf und legt entsprechende Actions pro Zeile fest. Manche Actions werden von den Benutzern auch von Hand eingetragen, weil der übermittelte Ablaufplan ungenau war. Irgendwann beginnt die Show und die Daten des Dienstleisters trudeln ein. Ab hier verändert sich der Inhalt des Ablaufplanes im Dataset dynamisch. Durch die Daten des Dienstleisters, durch Benutzereingaben, durch Timer, durch den Verlauf der Show. Viele dieser dynamischen Veränderungen bedingen eine veränderte Visualisierung. Etliche Prozeduren nehmen Änderungen an Zelleninhalten vor. Da bin ich bereits angekommen, das funktioniert soweit. Da ich die Farben nur ungern in den vielen Prozeduren, die die Zellinhalte verändern, setzen würde, war die Idee, dies schön zusammengefasst und an einem Ort zu erledigen. Daher die Idee mit der For-Each-Schleife in einer dedizierten Sub. Gute Idee?

    Ja, der Ablaufplan ist ziemlich linear. Fängt oben an und hört unten auf. Es gibt keine Sort on Columns oder sonstigen Filter. Und natürlich habe ich schon darüber nachgedacht, durch das DGV durchzutickern und die Daten da rauszupulen, aber dann wäre der Code nicht viel besser als vorher. :D

    Ein Beispiel: Zu einer bestimmten Uhrzeit ist ein Videobeitrag geplant. Dieser Beitrag ist aber bei Planerstellung noch nicht fertig. Im Plan ist nur der Dateiname des Files eingetragen. Im Schnittplatz wird der Beitrag erstellt und danach auf einen Server geschickt. Ein FileSystemWatcher überwacht diesen Ordner und setzt bei Vorhandensein des Files den entsprechenden State auf True, die Zelle soll grün werden. An anderer Stelle werden die Graphicinserts für den Beitrag erstellt und auch eine Datei mit den jeweiligen Timecodes. Jedes dieser Elemente wird fortwährend auf Präsenz auf dem Server überprüft. Die entsprechende Zelle soll grün werden. Sobald alle Elemente für den Beitrag vorhanden sind, soll die ganze Zeile grün werden. Das ist aktuell ziemlich umständlich mit Userpaints im Listview umgesetzt, das sollte mit einem DGV doch einfacher sein...

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Atreju.AZ“ ()

    Da die DGV-Daten die DataTable-Daten in selbiger Reihenfolge wiederzugeben scheinen, scheint der Code eigentlich easy:

    VB.NET-Quellcode

    1. For i = 0 To DataSetAblauf.Ablauf.Count - 1
    2. Dim AblaufRow = DataSetAblauf.Ablauf(i)
    3. If Wasauchimmer Then
    4. DeinDGV.Rows(i).DefaultCellStyle.Background = Drawing.Color.Yellow 'also färben, wenn nix anderes für die Zellen explizit festgelegt ist
    5. 'oder
    6. DataGridView1.Rows(1).Cells.Cast(Of DataGridViewCell).ToList.ForEach(Sub(x) x.Style.BackColor = Drawing.Color.Orange) 'bestimmte Farbe für alle Zellen festlegen
    7. 'oder
    8. DeinDGV.Rows(i).Cells(j).Style.Background = Drawing.Color.Yellow 'bestimmte Zellfarbe festlegen
    9. 'alternativ
    10. DeinDGV.Item(j, i).Style.Background = Drawing.Color.Yellow 'bestimmte Zellfarbe festlegen
    11. End If
    12. Next
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Eine letzte Frage hätte ich für heute noch, bevor ich das Gelernte heute Nacht umsetze: Das CellValueChanged-Ereignis des DGV wird nur ausgelöst, wenn im DGV selbst Änderungen vorgenommen werden. Gibt es ein entsprechendes Ereignis auf BindingSource- oder Datatable-Ebene?

    DANKE VIELMALS!
    LG
    Es gibt z.B. das BindingSource_CurrentItemChanged-Event. Die Frage ist nur: Wozu? Wodurch werden DataTable-Einträge geändert? Doch durch einen Daten-Import. Oder wie noch?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Im Ablauf stehen drei Videos hintereinander. Beim Startbefehl wird eine Playlist erzeugt und an das Playoutdevice geschickt. In der Playlist wird der Tableindex der drei Einträge mitgeliefert. Das Playoutdevice beginnt mit dem Abspielen und schickt den jeweiligen State zurück.

    VB.NET-Quellcode

    1. Dim ablaufrow = DataSetAblauf.Ablauf(20) 'die Row 20 enthält den Eintrag für das jetzt laufende Video
    2. ablaufrow.VideoEngine1State = "Playing" 'Oder eben "Cueing" oder "Done"


    Das Datagridview zeigt den State brav an, aber keines der Events wird ausgelöst. Nicht das CellValueChanged noch das CurrentItemChanged, weil es ja eben nicht zwangsweise das CurrentItem ist.

    Natürlich kann ich von überall dort, wo Inhalte auf die oben beschriebene Weise geändert werden, die Sub zum farbig-Pinseln zusätzlich aufrufen. Ich hoffte nur, das geht eleganter.
    Ja gut, gibt's verschiedene Events*, z.B. das CellValidating/CellValidated-Ereignis. Aber ich glaub, da wären wir schon falsch abgebogen.
    Um wieviele Codestellen geht es denn, die den DGV-Inhalt auf diese Weise indirekt ändern? Ließen die sich nicht sinnvoll zusammenfassen?

    * Wenn Du schauen willst, welche Events da ggf. infrage kommen: alle Events für ein Control loggen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Das sind leider einige... <X Habe gerade einmal zum Spaß das Ablauf-Listview gelöscht und der Compiler nörgelt an 813 Stellen. Diese Fleißarbeit habe ich schon beim Entfernen von anderen Listviews hinter mich gebracht. Nur nicht in diesem Ausmaß...

    Da ich die Stellen eh alle bearbeiten muss, schicke ich einfach überall da, woraus Daten geändert werden, ein Call DGV_Ablauf_Colors() hinterher. Die ist dank Deiner Hilfe schon weit fortgeschritten... DANKE! :)
    8| 813?!? Ich glaube, dass es da doch noch einige Punkte gibt, die am Code bearbeitet werden sollten. Naja, an solchen Projekten wächst man :thumbsup:
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Atreju.AZ schrieb:

    Gibt es ein entsprechendes Ereignis auf BindingSource- oder Datatable-Ebene?
    Der klassische (für mich) Weg, ein DGV zu colorieren ist das _CellPainting-Event.
    Das reagiert, wenn die an diese Zelle gebundenen Daten sich ändern.
    Oder vlt. besser das _RowPrepaint.
    Das reagiert, wenn sich was am gebundenen Datensatz was ändert - was ein Unterschied ist.

    Aber wenn du sagst, deine Colorierung ist irre kompliziert, kann das auch unzureichend sein - etwa wenn bei Änderung eines Datensatzes die nächstfolgende DGV-Zelle umcoloriert werden soll - sowas lässt sich mit _RowPrepaint nicht erschlagen.

    Aber kannst mal gugge coloriertes DatagridView
    Das zeigts mit _CellPainting.
    Ist auch eine Denk-Umstellung, weg von einer Schleife, die übers ganze DGV saust hin zur Betrachtung genau der einen Zelle, die im Begriff ist, sich neu zu zeichnen.

    ErfinderDesRades schrieb:

    Aber kannst mal gugge coloriertes DatagridView
    Das zeigts mit _CellPainting.
    Ist auch eine Denk-Umstellung, weg von einer Schleife, die übers ganze DGV saust hin zur Betrachtung genau der einen Zelle, die im Begriff ist, sich neu zu zeichnen.


    Vielen Dank für den Link! Ich schaue es mir an und denke mal drüber nach, vielleicht ist es die bessere Option!
    Danke und viele Grüße!