ListView-Gruppierung - komme nicht weiter

  • VB.NET
  • .NET 4.0

Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    ListView-Gruppierung - komme nicht weiter

    Moin zusammen.

    Ich bastel' grad ne ListView zusammen, das Befüllen an sich klappt einwandfrei.
    Jetzt möchte ich noch die Möglichkeit hinzufügen, komplette Rows zu gruppieren und da hängt's.
    Im Konkreten soll hier nach Abteilung gruppiert werden. Ist die Gruppe bereits vorhanden (Also die Abteilung mit dem Namen ist schonmal vorgekommen),
    dazu gibts die grpExist-Funktion,
    dann sollen die Rows der bereits bestehenden Gruppe hinzugefügt werden, ansonsten eine neue erstellen und die darein packen.
    Mit dem folgenden Code erhält jede Zeile ihre eigene Gruppe (logisch, denn Zeile 17 sagt ja "füg' die Gruppe dem LV hinzu", obwohl die ggf. schon existiert)
    Wo hab' ich denn hier den Denkfehler? Nehme ich Zeile 18 statt 17 zeigt garnix an und meckert schon über Zeile 22, dass das Item nur einmal zugefügt werden kann ?(

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Function grpExist(group As ListViewGroup) As Boolean
    2. Dim exist = False
    3. For Each grp As ListViewGroup In lvMitarbeiter.Groups
    4. If grp.Name = group.Name Then
    5. exist = True
    6. End If
    7. Next
    8. Return exist
    9. End Function
    10. Private Sub PlanDatenMitarbeiter(rwMitarbeiter As MitarbeiterRow)
    11. lvMitarbeiter.ShowGroups = True
    12. Dim grp As New ListViewGroup
    13. grp.Header = rwMitarbeiter.Abteilung
    14. grp.Name = rwMitarbeiter.Abteilung
    15. With lvMitarbeiter.Groups
    16. .Add(grp) ' -> macht logischerweise jede Zeile in eine eigene Gruppe
    17. 'If Not grpExist(grp) = True Then .Add(grp) -> geht nicht
    18. Dim lvItem As New ListViewItem
    19. lvItem = lvMitarbeiter.Items.Add(rwMitarbeiter.expFullname)
    20. lvItem.Group = grp
    21. lvItem.SubItems.Add(rwMitarbeiter.expGesellschaft)
    22. lvItem.SubItems.Add(rwMitarbeiter.Standort)
    23. lvItem.SubItems.Add(rwMitarbeiter.Abteilung)
    24. lvItem.SubItems.Add(rwMitarbeiter.Urlaubsanspruch.ToString)
    25. Dim anzahlUrlaub As Double = 0
    26. For Each rwPlan In dts.Plan
    27. If rwPlan.MitarbeiterID = rwMitarbeiter.ID Then
    28. If rwPlan.Datum.Year.ToString = My.Settings.TabbedJahr Then
    29. If rwPlan.Status = "U" Then
    30. anzahlUrlaub += 1
    31. ElseIf rwPlan.Status = "hU" Then
    32. anzahlUrlaub += 0.5
    33. End If
    34. End If
    35. End If
    36. Next
    37. lvItem.SubItems.Add(anzahlUrlaub.ToString)
    38. Dim unverplant As Double = rwMitarbeiter.Urlaubsanspruch - anzahlUrlaub
    39. lvItem.UseItemStyleForSubItems = False
    40. If unverplant < 0 Then
    41. lvItem.SubItems.Add(unverplant.ToString).BackColor = Color.LightCoral
    42. Else
    43. lvItem.SubItems.Add(unverplant.ToString)
    44. End If
    45. Dim anzahlKrank As Double = 0
    46. For Each rwPlan In dts.Plan
    47. If rwPlan.MitarbeiterID = rwMitarbeiter.ID Then
    48. If rwPlan.Datum.Year.ToString = My.Settings.TabbedJahr Then
    49. If rwPlan.Status Like "K" Then
    50. anzahlKrank += 1
    51. End If
    52. End If
    53. End If
    54. Next
    55. If anzahlKrank > 10 Then
    56. lvItem.SubItems.Add(anzahlKrank.ToString).BackColor = Color.LightCoral
    57. Else
    58. lvItem.SubItems.Add(anzahlKrank.ToString)
    59. End If
    60. End With
    61. End Sub

    Bilder
    • unbenannt1.png

      230,96 kB, 1.113×1.582, 28 mal angesehen
    Originaler (noch) Nichtskönner :D

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

    Deine grpExist()-Methode solltest du dahingehend umbauen, dass sie dir eine ListViewGroup mit dem übergebenen Namen zurückliefert, welche von der Methode notfalls selbständig erzeugt wird.

    VB.NET-Quellcode

    1. Private Shared Function GetGroup(lv As ListView, name As String) As ListViewGroup
    2. For Each grp As ListViewGroup In lv.Groups
    3. If grp.Name = name Then
    4. Return grp
    5. End If
    6. Next
    7. Dim newGrp = New ListViewGroup(name, name)
    8. lv.Groups.Add(newGrp)
    9. Return newGrp
    10. End Function


    Aufruf:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub PlanDatenMitarbeiter(rwMitarbeiter As MitarbeiterRow)
    2. lvMitarbeiter.ShowGroups = True
    3. With lvMitarbeiter.Groups
    4. Dim grp = GetGroup(lvMitarbeiter, rwMitarbeiter.Abteilung)
    5. Dim lvItem As New ListViewItem
    6. lvItem = lvMitarbeiter.Items.Add(rwMitarbeiter.expFullname)
    7. lvItem.Group = grp
    8. lvItem.SubItems.Add(rwMitarbeiter.expGesellschaft)
    9. lvItem.SubItems.Add(rwMitarbeiter.Standort)
    10. lvItem.SubItems.Add(rwMitarbeiter.Abteilung)
    11. lvItem.SubItems.Add(rwMitarbeiter.Urlaubsanspruch.ToString)
    12. Dim anzahlUrlaub As Double = 0
    13. For Each rwPlan In dts.Plan
    14. If rwPlan.MitarbeiterID = rwMitarbeiter.ID Then
    15. If rwPlan.Datum.Year.ToString = My.Settings.TabbedJahr Then
    16. If rwPlan.Status = "U" Then
    17. anzahlUrlaub += 1
    18. ElseIf rwPlan.Status = "hU" Then
    19. anzahlUrlaub += 0.5
    20. End If
    21. End If
    22. End If
    23. Next
    24. lvItem.SubItems.Add(anzahlUrlaub.ToString)
    25. Dim unverplant As Double = rwMitarbeiter.Urlaubsanspruch - anzahlUrlaub
    26. lvItem.UseItemStyleForSubItems = False
    27. If unverplant < 0 Then
    28. lvItem.SubItems.Add(unverplant.ToString).BackColor = Color.LightCoral
    29. Else
    30. lvItem.SubItems.Add(unverplant.ToString)
    31. End If
    32. Dim anzahlKrank As Double = 0
    33. For Each rwPlan In dts.Plan
    34. If rwPlan.MitarbeiterID = rwMitarbeiter.ID Then
    35. If rwPlan.Datum.Year.ToString = My.Settings.TabbedJahr Then
    36. If rwPlan.Status Like "K" Then
    37. anzahlKrank += 1
    38. End If
    39. End If
    40. End If
    41. Next
    42. If anzahlKrank > 10 Then
    43. lvItem.SubItems.Add(anzahlKrank.ToString).BackColor = Color.LightCoral
    44. Else
    45. lvItem.SubItems.Add(anzahlKrank.ToString)
    46. End If
    47. End With
    48. End Sub



    Verbesserungsvorschlag:
    Spoiler anzeigen

    Du solltest es dir angewöhnen Darstellung und Logik besser zu trennen. Angenommen du findest morgen ein Steuerelement, welches die Auswertung besser darstellen könnte - Jetzt musst du praktisch die komplette Auswertung der Mitarbeiter und deren Daten überarbeiten, obwohl die Ermittlungslogik identisch bleibt -> nicht gut.

    Zuerst eine Datenklasse für die Auswertung definieren:

    VB.NET-Quellcode

    1. Public Class EmployeeEvaluationData
    2. Public Property Name As String
    3. Public Property Department As String
    4. Public Property HolidaysDays As Double
    5. Public Property SicknessDays As Double
    6. Public Sub New(name As String, department As String, holidaysDays As Double, sicknessDays As Double)
    7. Me.Name = name
    8. Me.Department = department
    9. Me.HolidaysDays = holidaysDays
    10. Me.SicknessDays = sicknessDays
    11. End Sub
    12. End Class


    Dann eine Methode, die die Daten ermittelt und aufbereitet:

    VB.NET-Quellcode

    1. Public Shared Function GetPlanDataEmployees() As IEnumerable(Of IGrouping(Of String, EmployeeEvaluationData))
    2. Dim employeesEvaluation = New List(Of EmployeeEvaluationData)()
    3. For Each employee In dts.Mitarbeiter
    4. Dim SicknessDays = 0R
    5. Dim holidaysDays = 0R
    6. For Each plans In employee.GetPlanRows()
    7. If plans.Status = "U" Then
    8. holidaysDays += 1.0R
    9. ElseIf plans.Status = "hU" Then
    10. holidaysDays += 0.5R
    11. ElseIf plans.Status Like "K" Then
    12. SicknessDays += 1.0R
    13. End If
    14. Next
    15. employeesEvaluation.Add(New EmployeeEvaluationData(employee.Name,
    16. employee.Abteilung,
    17. holidaysDays,
    18. SicknessDays))
    19. Next
    20. Return employeesEvaluation.GroupBy(Function(x) x.Department)
    21. End Function


    Und eine die diese Daten darstellt:

    VB.NET-Quellcode

    1. Private Sub PlanDatenMitarbeiter()
    2. lvMitarbeiter.ShowGroups = True
    3. For Each department In GetPlanDataEmployees()
    4. Dim grp As New ListViewGroup
    5. grp.Header = department.Key
    6. grp.Name = department.Key
    7. lvMitarbeiter.Groups.Add(grp)
    8. For Each employee In department
    9. Dim lvItem = lvMitarbeiter.Items.Add(employee.Name)
    10. lvItem.Group = grp
    11. lvItem.SubItems.Add(employee.Department)
    12. lvItem.SubItems.Add(employee.HolidaysDays.ToString())
    13. lvItem.SubItems.Add(employee.SicknessDays.ToString())
    14. Next
    15. Next
    16. End Sub

    Bilder
    • Ausgabe.PNG

      18,95 kB, 468×628, 26 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ChristianT.“ ()

    ChristianT. schrieb:

    Deine grpExist()-Methode solltest du dahingehend umbauen, dass sie dir eine ListViewGroup mit dem übergebenen Namen zurückliefert, welche von der Methode notfalls selbständig erzeugt wird.

    WOW 8o 8o
    Die 1. Methode läuft schon wie gewünscht. Vielen Dank!


    bzgl. Trennung Logik und Darstellung:
    perfekt, genau sowas in die Richtung hatte ich gesucht. Ist jetzt bei dem Planer-Projekt nicht ganz so wichtig, aber für mein Hauptprojekt eignet sich sowas außerdordentlich gut.
    Ich werd' mich damit definitiv mal auseinandersetzen - ich denke, das wird mir für meine Rechtesteuerung zugute kommen :thumbup:
    Originaler (noch) Nichtskönner :D