DataGrid - elegantere Lösung zum markieren?

  • VB.NET

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von hate_regex.

    DataGrid - elegantere Lösung zum markieren?

    Servus!

    Aktuell habe ich ein Datagrid, dass mit n-Werten befüllt ist. Diese Werte prüfe ich auf Gültigkeit und markiere im Anschluss die Zellen farblich.
    Wenn ich mir jedoch meinen Code ansehe, bin ich mir sicher, dass man hierfür eine elegantere Lösung finden kann, als durch die Case-Selection. Ich würde es gerne als Funktion auslagern. Hat jemand eine Idee wie man das geschickterweise angehen kann?

    VB.NET-Quellcode

    1. Private Sub Check_Cell()
    2. Dim Zelle As DataGridViewCell
    3. For Each Zelle In DataGrid.SelectedCells
    4. Select Case Zelle.ColumnIndex
    5. Case 0
    6. If SID(CStr(Zelle.Value)) = True Then
    7. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Green
    8. Else
    9. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Red
    10. End If
    11. Case 3
    12. If ORE(CStr(Zelle.Value)) = True Then
    13. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Green
    14. Else
    15. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Red
    16. End If
    17. Case 5
    18. If KOS(CStr(Zelle.Value), "STRING") = True Then
    19. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Green
    20. Else
    21. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Red
    22. End If
    23. Case 6
    24. If PID(CStr(Zelle.Value)) = True Then
    25. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Green
    26. Else
    27. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Red
    28. End If
    29. Case 7
    30. If KID(CStr(Zelle.Value)) = True Then
    31. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Green
    32. Else
    33. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Red
    34. End If
    35. Case 8
    36. If STID(CStr(Zelle.Value)) = True Then
    37. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Green
    38. Else
    39. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = Color.Red
    40. End If
    41. End Select
    42. DataGrid.ClearSelection()
    43. Next
    44. End Sub


    Wie man sieht, letztlich nur eine Code/Case-Wiederholung in dem sich nur der Funktionsaufruf unterscheidet.

    Danke! :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hate_regex“ ()

    hate_regex schrieb:

    Codewiederholen/Case
    Dann solltest Du im Select Case lediglich ein Flag setzen und dies darunter auswerten:

    VB.NET-Quellcode

    1. Dim Flag As Boolean
    2. ' ...
    3. Case xx
    4. Flag = SID(CStr(Zelle.Value))
    5. ' ...
    6. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = If (Flag, Color.Green, Color.Red)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Ich habe deinen Vorschlag umgesetzt, schien mir passend:

    VB.NET-Quellcode

    1. Dim Flag As Boolean
    2. For Each Zelle In DataGrid.SelectedCells
    3. Select Case Zelle.ColumnIndex
    4. Case 0, 14
    5. Flag = SID(CStr(Zelle.Value))
    6. Case 3
    7. Flag = ORE(CStr(Zelle.Value))
    8. Case 5
    9. Flag = KOS(CStr(Zelle.Value), "STRING")
    10. Case 6
    11. Flag = PID(CStr(Zelle.Value))
    12. Case 7
    13. Flag = KID(CStr(Zelle.Value))
    14. Case 8
    15. Flag = STID(CStr(Zelle.Value))
    16. Case Else
    17. Flag = False
    18. End Select
    19. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = If(Flag, Color.Green, Color.Red
    )
    Da hätte ich jetzt noch 1-2 Rückfragen, wenn genehm..
    Ich muss zwingend ein Case Else setzen. Zellen die nicht geprüft werden, haben somit ein False.
    Nun möchte ich jedoch die nicht geprüften Zellen grau einfärben. Die Abfrage ist jedoch eine boolsche. Wie kann ich in die IF-Selection ein Else einbauen, oder eine dritte Farbe für ungeprüfte Zellen setzen?

    Danke!
    Da brauchst Du ein weiteres Flag oder ein enum.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke, Rod.. mit Enum funktioniert es.

    Eine Frage hätte ich noch:
    Ich selektiere eine gewisse Anzahl von Cells (selected) und färbe diese nach Prüfung entsprechend um. Anschließend ein DataGrid.ClearSelection()
    Nun möchte ich jedoch, dass die markierten Zellen jeweils einzeln deselektiert werden um den Fortschritt erkennbar zu machen. Ich habe es so versucht (innerhalb der For Each Schleife, ausserhalb der Case-Selection):

    VB.NET-Quellcode

    1. DataGrid.SelectedRows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Selected = False
    bzw.

    VB.NET-Quellcode

    1. DataGrid.CurrentCell = DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex)
    2. DataGrid.CurrentCell.Selected = False


    und bekomme nachfolgende Fehlermeldung:

    Quellcode

    1. Der Index lag außerhalb des Bereichs. Er muss nicht negativ und kleiner als die Auflistung sein.
    2. Parametername: index
    3. + Zelle {DataGridViewTextBoxCell { ColumnIndex=5, RowIndex=3 }} System.Windows.Forms.DataGridViewCell


    In beiden Fällen wird die CellSelection nicht nach der Prüfung aufgehoben, sondern entweder alle gleichzeitig oder nur der erste Eintrag.
    Was stimmt da nicht?

    Danke!
    Auf welche von beiden Möglichkeiten bezieht sich deine Fehlermeldung?
    Der Index von "Zelle" bezieht sich auf die Aufzählung in "SelectedCells", ist er denn auch absolute Index von "Rows" (im 2. Beispiel)? Fängt die Zählung innerhalb von SelectedCells wieder von 0 an oder ist es immer absolute Index? Das musst du prüfen.

    hate_regex schrieb:

    Was stimmt da nicht?
    Setz einen Haltepunkt drauf und sieh Dir die Werte der Indizes an.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Auf welche von beiden Möglichkeiten bezieht sich deine Fehlermeldung?
    Die Erste Variante.

    VB.NET-Quellcode

    1. For Each Zelle In DataGrid.SelectedCells
    2. Select Case Zelle.ColumnIndex
    3. '...
    4. End Select
    5. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Style.ForeColor = If(Flag, Color.Green, Color.White)
    6. Next



    Der Index sollte absolut sein, da ich diesen (s.o.) auch zum umfärben verwende.
    Bei der farblichen Markierung funktioniert es. Bei der anschließenden Deselection nicht.

    Haltepunkte habe ich gesetzt:



    .. ich kann nicht erkennen, warum der Index außerhalb des Bereichs liegen soll (Grid hat 14 Columns, 100+ Rows)

    Edit:
    Ich bin ein Trottel!:

    VB.NET-Quellcode

    1. DataGrid.Rows(Zelle.RowIndex).Cells(Zelle.ColumnIndex).Selected = False
    Sorry, dass ich das Thema nochmal ausgrabe, aber meine Frage ist sehr verwandt:

    @RodFromGermany
    Du hattest oben vorgeschlagen:
    Da brauchst Du ein weiteres Flag oder ein enum.


    Ich habe es über einen Enumerator gelöst bekommen. Für eine anderes Problem würde ich nun gerne auf die Variante mit einem 2. Flag zurückgreifen.
    Soweit im Prinzip auch klar, jedoch habe ich Probleme mit Umsetzung.

    Nach der Schleifenauswertung hattest du es über eine boolsche Abfrage ausgewertet:

    VB.NET-Quellcode

    1. If(Flag, Color.Green, Color.White)

    Bei 3 Statements bleibt also nur die Möglichkeit, dass wieder über eine Schleife/Case Selection zu lösen. Oder?
    Möchte vermeiden, dass der Code am Ende wie ein italienischen Nudelgericht ausschaut.
    Überleg mal selbst, ein Flag ist 1 Bit, also 2^1 Möglichkeiten = 2. 2 Flags sind 2 Bit, also 2^2 Möglichkeiten. Du musst deine Flags also verunden (AndAlso), wenn du so machen willst.
    Flag1 Flag2
    0 ........0 = Möglichkeit 1
    0 ........1 = Möglichkeit 2
    1 ........0 = Möglichkeit 3
    1 ........1 = nicht benutzt