I need your help: i need to change background color of listview items after created it. Specifically: when creating the listview I colored the lines alternately with two different colors (two different shades of gray). Clicking on the column header reorder the rows according to a different criterion depending on the column. This rearrangement means that the alternation of colors is no longer guaranteed.I would like to recolor the items exactly as in the creation phase keeping the sort.
Hi, testing your code, I noticed that I had a problem with the sortview of the listview. My listview contains a list of films grouped by initial title and there are 4 columns: title, rating, year and duration.Clicking on the columns should cause sorting in this way: Group (Descending) -> Title (Descending) -> Group (Ascending) -> Title (Ascending).
If I click on the "Title" column everything works correctly (including colors), if I click on another column the sorting works but the colors remain untidy.
I am convinced that I have mistaken the sorting algorithm (I ordered by group and, subsequently, by item but I do not know how to order at the same time for both types.) I quote the part of the code I wrote for completeness
Thanks
Semola
Private Sub lvFilmDetail_ColumnClick(sender As Object, e As ColumnClickEventArgs) Handles lvFilmDetail.ColumnClick
swc_item_checked = False
If ws_column_svd <> e.Column Then
ws_group_sorting = SortOrder.Ascending
If e.Column = 1 Then
ws_item_sorting = SortOrder.Descending
Else
ws_item_sorting = SortOrder.Ascending
End If
ctr_sort = 0
ws_column_svd = e.Column
Else
If lvFilmDetail.ShowGroups Then
Dim ws_mod_sort = ctr_sort Mod 4
Select Case ws_mod_sort
Case 0, 2
ws_item_sorting = ImpostaSorting(ws_item_sorting)
Case 1, 3
ws_group_sorting = ImpostaSorting(ws_group_sorting)
ws_item_sorting = ImpostaSorting(ws_item_sorting)
End Select
Else
ws_item_sorting = ImpostaSorting(ws_item_sorting)
End If
End If
If lvFilmDetail.ShowGroups Then
Dim ws_mod_sort = ctr_sort Mod 4
Select Case ws_mod_sort
Case 0, 2
lvFilmDetail.ListViewItemSorter = New CompareByName(e.Column, ws_item_sorting)
lvFilmDetail.Sort()
Case 1, 3
Dim listGroups As List(Of ListViewGroup) = lvFilmDetail.Groups.Cast(Of ListViewGroup).ToList
listGroups.Sort(New ListViewGroupHeaderSorter(ws_group_sorting))
lvFilmDetail.Groups.Clear()
lvFilmDetail.Groups.AddRange(listGroups.ToArray)
lvFilmDetail.ListViewItemSorter = New CompareByName(e.Column, ws_item_sorting)
lvFilmDetail.Sort()
End Select
ctr_sort += 1
Else
lvFilmDetail.ListViewItemSorter = New CompareByName(e.Column, ws_item_sorting)
lvFilmDetail.Sort()
End If
For Each item As ListViewItem In lvFilmDetail.Items
item.BackColor = If(item.Index Mod 2 = 0, Color.FromArgb(255, 240, 240, 240), Color.FromArgb(255, 210, 210, 210))
Next
swc_item_checked = True
End Sub
Private Function ImpostaSorting(ByVal InSorting As SortOrder) As SortOrder
If InSorting = SortOrder.Ascending Then
Return SortOrder.Descending
Else
Return SortOrder.Ascending
End If
End Function
'--------------------------------
Class CompareByName
Implements IComparer
Dim index As Integer
Dim m_sortorder As SortOrder
Sub New(ByVal subItemIndex As Integer, ByVal sortOrder As SortOrder)
index = subItemIndex
m_sortorder = sortOrder
End Sub
Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
Dim item1 As ListViewItem = CType(x, ListViewItem)
Dim item2 As ListViewItem = CType(y, ListViewItem)
If m_sortorder = SortOrder.Ascending Then
Return String.Compare(item1.SubItems(index).Text, item2.SubItems(index).Text)
Else
Return String.Compare(item2.SubItems(index).Text, item1.SubItems(index).Text)
End If
End Function
End Class
Class CompareByDate
Implements IComparer
Dim index As Integer
Dim m_sortorder As SortOrder
Sub New(ByVal subItemIndex As Integer, ByVal sortOrder As SortOrder)
index = subItemIndex
m_sortorder = sortOrder
End Sub
Public Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
Dim item1 As ListViewItem = CType(x, ListViewItem)
Dim item2 As ListViewItem = CType(y, ListViewItem)
If m_sortorder = SortOrder.Ascending Then
Return Date.Compare(Date.Parse(item1.SubItems(index).Text), Date.Parse(item2.SubItems(index).Text))
Else
Return Date.Compare(Date.Parse(item2.SubItems(index).Text), Date.Parse(item1.SubItems(index).Text))
End If
End Function
End Class
Public Class ListViewGroupHeaderSorter
Implements IComparer(Of ListViewGroup)
Dim RequiredSortOrder As SortOrder
Public Sub New(ByRef RequiredOrder As SortOrder)
RequiredSortOrder = RequiredOrder
End Sub
Public Function Compare(ByVal FirstHeader As ListViewGroup, ByVal SecondHeader As ListViewGroup) As Integer Implements IComparer(Of ListViewGroup).Compare
If RequiredSortOrder = SortOrder.Ascending Then
Return String.Compare(FirstHeader.Header, SecondHeader.Header)
Else
Return String.Compare(SecondHeader.Header, FirstHeader.Header)
End If
End Function
End Class
The order of the Items collection does not necessarily match what you see if the items are grouped. Without having tested it, I think that something like this should work:
Dim itemBackColor = Color.LightBlue
For Each group As ListViewGroup In ListView1.Groups
For Each item As ListViewItem In group.Items
item.BackColor = itemBackColor
'Toggle the colour for the next item.
itemBackColor = If(itemBackColor = Color.LightBlue,
Color.LightGreen,
Color.LightBlue)
Next
Next
I have the same problem.
I have solved with this code, but I read all listview items (excluding all those who have a different group).
Dim itemBackColor = Color.FromArgb(255, 240, 240, 240)
For Each group As ListViewGroup In lvFilmDetail.Groups
For Each item As ListViewItem In lvFilmDetail.Items
If item.Group.Header = group.Header Then
item.BackColor = itemBackColor
itemBackColor = If(itemBackColor = Color.FromArgb(255, 240, 240, 240),
Color.FromArgb(255, 210, 210, 210), Color.FromArgb(255, 240, 240, 240))
End If
Next
Next
Avoid what logic? That code does what it does. If you want to do something else then use other code. I don't know what you want to do exactly so I don't know what code would do it.
One thing I would say is don't ever do what you're doing there and keep repeating the same thing over and over like that. There's no good reason to call Color.FromArgb repeatedly when you know that the results will be the same every time. Do it once, assign the result to a variable and then use that over and over.
Dim firstColor = Color.FromArgb(240, 240, 240)
Dim secondColor = Color.FromArgb(210, 210, 210)
Dim itemBackColor = firstColor
For Each group As ListViewGroup In lvFilmDetail.Groups
For Each item As ListViewItem In lvFilmDetail.Items
If item.Group.Header = group.Header Then
item.BackColor = itemBackColor
itemBackColor = If(itemBackColor = firstColor,
secondColor,
firstColor )
End If
Next
Next
Note also that there's no need to specify the alpha component unless you want transparency because it defaults to 255.
Just a tip for code you posted, you can compare the group objects rather than their header strings:
If item.Group Is group Then
As for another logic, the group items are not returned in sort order, but their Index order is valid, so you can do this:
For Each group As ListViewGroup In Me.ListView1.Groups
Dim sorted = (From item As ListViewItem In group.Items Order By item.Index).ToArray
For i = 0 To sorted.Count - 1
sorted(i).BackColor = If(i Mod 2 = 0, Color.LightBlue, Color.LightGreen)
Next
Next
Thanks to jmcilhinney for pointing this out in another forum not long ago
I recall the thread you're talking about but not it's content. I do recall I spent a fair bit of time testing on that occasion because things did not work at all as expected.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.