I have a ListView control on a tab page. The backcolor of the items of the ListView are changed according to certain criteria, but whether or not the backcolor changes appears to be pretty random.

The tab page containing the ListView is not the default tab page on application startup. On application startup, the ListView is updated. It displays a list of documents populated from a text file (which contains the list of documents and information such as most recent update time) and then changes the backcolor according to the most recent update time. The ListView is also updated every time the user enters the containing tab page.

In debug mode, the backcolors display as intended every time. When actually running the application, however, the colours don't appear immediately about 60% of the time. Let me explain more. There are about 500 items in the ListView so a vertical scrollbar is necessary to view them all. Upon entering the containing tab page, the backcolor of the visible items is white. Scrolling down reveals further items, but they are coloured properly. Scrolling back up reveals all of the items to be coloured properly.

I'm out of ideas as to what could be causing this. I've tried a ListView.Refresh() statement at the end of the method that populates and colours the ListView, but to no avail (this fixed it in debug mode, but not in the published application - yes, it did update).

Currently the method that colours the ListView is something like the below. Please note that the arrays documentNames and documentUpdates, and the item collection of ListView are all linked so that item x in ListView has the name at position x in documentNames and was most recently updated on the date at position x in documentUpdates.

Friend Sub ListViewUpdate()
    Dim initialised As Boolean = False

    While Not initialised
        ListView.Items.Clear()

        ' Iterate through files in the containing directory and add document names to
        ' an array, documentNames

        ' Sort documentNames alphanumerically

        ' Find the date of the most recent change to each document and store it in the
        ' appropriate element of another array, documentUpdates

        ' Populate the ListView with the elements from documentNames

        ' Colour each item in ListView according to the difference between the current
        ' date and the date stored in the corresponding element of documentUpdates

        initialised = True
        ListView.Refresh()
    End While

End Sub

Any advice that could help me fix this (not disastrous, but annoying) bug would be appreciated! I can provide more detailed code if needed.

"Something like" code can't be debugged. What I can do with what you have shown is offer some code that does what I think you want. The following scans the "My Documents" folder on my D: drive and colours the lines based on the age (in months) if the files.

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load

        For Each file As String In My.Computer.FileSystem.GetFiles("D:\My Documents")

            Dim filepart As String = System.IO.Path.GetFileName(file)
            Dim filedate As Date = My.Computer.FileSystem.GetFileInfo(file).LastWriteTime

            Dim item As New ListViewItem(filepart)

            Select Case DateDiff(DateInterval.Month, filedate, Now)
                Case Is < 10
                    item.BackColor = Color.LightGreen
                Case Is < 20
                    item.BackColor = Color.LightCyan
                Case Is < 50
                    item.BackColor = Color.LightPink
                Case Else
                    item.BackColor = Color.LightSalmon
            End Select

            ListView1.Items.Add(item)

        Next

    End Sub

End Class

Thanks for the response once again Reverend Jim! I thought that perhaps your declaration of item, and later editing of its properties, before adding it to the ListView would solve the problem. But it hasn't, unfortunately.

I'm sorry that I didn't post the code as a whole. The method is quite long and I didn't want to distract from the issue or clutter the code with what might be irrelevent statements.

I feel like the issue is probably something to do with the way VB.NET updates its controls and when. At the moment, as mentioned, the ListView.Refresh() statement occurs at the end of the ListViewUpdate() method. I've tried the refresh outisde of the method too, in the method that calls ListViewMethod() and after that call. There is no difference. It's also odd that this is only an issue in the publish application and not during debug. Is it likely that this is a problem that has nothing to do with the code, but the computer on which the application is running?

Is the client computer running .NET Framework 4.0 Client while the dev machine is running Full?

I have had issues with client Vs. full before. I wouldn't rule that out completely.

Thanks for the suggestion Begginnerdev. The development machine and client computer are one and the same - at this stage, I'm testing it all on the same computer.

After doing a little research, I have found some possible fixes:

Set the ListView's HideSelection property to true

Some one has suggested useing Invalidate(), allowing the listview to repaint at the next paint action. (Less taxing)

I will continue looking.

The HideSelection property is already True. I tried using ListView.Invalidate() at the start of the method that updates the backcolors but it didn't seem to do anything. The backcolors still appear just fine in debug but not on the published application.

The color is not applied to only the viewable area of the data?

Initially, yes, that's correct i.e., the visible area upon entering the tab page containing the ListView is not coloured correctly. Scrolling down the ListView reveals correctly coloured items, and scrolling back to the top will reveal the initial area to now be coloured. The scrolling is not linked to any method, so no additional code (that I've written, at least) is being read as the ListView is scrolled. It must be something to do with the way the form updates. But it is baffling that everything would be fine in debug mode but not in the published application.

Can you post a snipped of the code that loads/colors the listview items?

I see that you are coloring after you populate, why not color while you populate?

The snippet of code controlling the colours of the ListView is shown below. Note that: documentNames is an array that is self-descriptive, launchDirectory is the location of the documents in documentNames, documentUpdates is another array that contains the most recent update time for the corresponding document in documentNames, and ChangelogList is the ListView in question.

For Each document In documentNames
                    If Not String.IsNullOrWhiteSpace(document) And _
                        My.Computer.FileSystem.FileExists( _
                        My.Settings.launchDirectory & document & ".xlsx") Then
                        'ChangelogList.Items.Add(document.ToString() & ".xlsx")
                        Dim item As New ListViewItem(document.ToString & ".xlsx")

                        Select Case DateDiff(DateInterval.Day, _
                                             documentUpdates.GetValue(index), _
                                             DateTime.Now)
                            Case Is <= 1
                                item.BackColor = Color.DarkRed
                                item.ForeColor = Color.White
                            Case Is <= 2
                                item.BackColor = Color.Red
                                item.ForeColor = Color.Black
                            Case Is <= 3
                                item.BackColor = Color.Crimson
                            Case Is <= 7
                                item.BackColor = Color.PaleVioletRed
                            Case Is <= 30
                                item.BackColor = Color.Pink
                        End Select

                        ChangelogList.Items.Add(item)
                        index += 1
                    End If
                Next

I did initially colour after I populated and wondered if this might be the problem after looking at Reverend Jim's code. As you can see, I've changed it so that it now colours while it populates, as per the example.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.