Link to home
Start Free TrialLog in
Avatar of gozza11
gozza11

asked on

items.clear not working to clear listview?

for some strange reason i can resize my form and clear the items yet every now and then it crashes tellin me "Object reference not set to an instance of an object"??

i have posted the code below but im not sure why it shouldnt work because it does for a litle while and then crashes afterwards.

Thanks
Gozza


here is the code:

-------------------------------------------------------------------------------------------------------------------

    Public PreviousVItemCount As String
    Public TestArray(40) As ListViewItem
    Public FormLoaded As Boolean = False

    Public Sub Populate()

        With lvwLibrary2

            Dim i As Integer
            Dim ColWidth As Integer
            Dim VitemCount As String

            For i = 0 To .Columns.Count - 1
                ColWidth += .Columns(i).Width
            Next

            If ColWidth > .Width Then
                VitemCount = (.Height - 39) / 14
            Else
                VitemCount = (.Height - 19) / 14
            End If

            If VitemCount.IndexOf(".") > 0 Then
                VitemCount = VitemCount.Substring(0, VitemCount.IndexOf("."))
            ElseIf VitemCount.IndexOf(".") = 0 Then
                VitemCount = 0
            End If


            If Not VitemCount = PreviousVItemCount Then

                scrollV.Maximum = TestArray.Length + 8

                    If .Items.Count > 0 Then
                        .Items.Clear()
                    End If

                For i = 0 To VitemCount - 1
                    Try
                        .Items.Add(TestArray(scrollV.Value + i).Clone)
                    Catch ex As Exception
                        MsgBox(ex.Message)
                    End Try
                Next

                PreviousVItemCount = VitemCount

            End If


        End With

    End Sub
    Public Sub Scroll()

        With lvwLibrary2
            If scrollV.Value < OldValue Then
                .Items(.Items.Count - 1).Remove()
                .Items.Insert(0, TestArray(scrollV.Value).Clone)

            ElseIf scrollV.Value > OldValue Then
                .Items(0).Remove()
                .Items.Add(TestArray(scrollV.Value).Clone)
            End If

            OldValue = scrollV.Value
        End With

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Populate()       'this works fine, only crashes when it resizes
    End Sub

    Private Sub scrollV_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles scrollV.Scroll
        Scroll()
    End Sub

    Private Sub lvwLibrary2_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lvwLibrary2.SizeChanged
        If FormLoaded Then
            Populate()
        End If
    End Sub

    Private Sub frmOptions_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Integer
        For i = 0 To 40
            Dim item As New ListViewItem
            item.Text = "test - " & i
            item.SubItems.Add("test - " & i)
            TestArray(i) = item
        Next
        FormLoaded = True
    End Sub

---------------------------------------------------------------------------------------------------------------
ASKER CERTIFIED SOLUTION
Avatar of GohdanTheMoblin
GohdanTheMoblin

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gozza11
gozza11

ASKER

ok that seems to have made things work, yet it crashed when it was trying to clear the items. but u said there is a better way to get the items into the array. can u please explain how?

thanks
goz
Hai,

Check the below code... It's working great.

The problem with your code is Populate() function is running multiple times as it's called on lvwLibrary2_SizeChanged event. So i've added a boolean variable ivlLodingList to check whether populate() function is running if not it will get called.

Public Class SystemTray
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Private WithEvents NotifyIcon1 As System.Windows.Forms.NotifyIcon
    Friend WithEvents ContextMenu1 As System.Windows.Forms.ContextMenu
    Friend WithEvents mnuShow As System.Windows.Forms.MenuItem
    Friend WithEvents mnuHide As System.Windows.Forms.MenuItem
    Friend WithEvents lvwLibrary2 As System.Windows.Forms.ListView
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents scrollV As System.Windows.Forms.VScrollBar
    Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader
    Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(SystemTray))
        Me.NotifyIcon1 = New System.Windows.Forms.NotifyIcon(Me.components)
        Me.ContextMenu1 = New System.Windows.Forms.ContextMenu
        Me.mnuShow = New System.Windows.Forms.MenuItem
        Me.mnuHide = New System.Windows.Forms.MenuItem
        Me.lvwLibrary2 = New System.Windows.Forms.ListView
        Me.Button1 = New System.Windows.Forms.Button
        Me.scrollV = New System.Windows.Forms.VScrollBar
        Me.ColumnHeader1 = New System.Windows.Forms.ColumnHeader
        Me.ColumnHeader2 = New System.Windows.Forms.ColumnHeader
        Me.SuspendLayout()
        '
        'NotifyIcon1
        '
        Me.NotifyIcon1.ContextMenu = Me.ContextMenu1
        Me.NotifyIcon1.Icon = CType(resources.GetObject("NotifyIcon1.Icon"), System.Drawing.Icon)
        Me.NotifyIcon1.Text = "Notify"
        Me.NotifyIcon1.Visible = True
        '
        'ContextMenu1
        '
        Me.ContextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuShow, Me.mnuHide})
        '
        'mnuShow
        '
        Me.mnuShow.Index = 0
        Me.mnuShow.Text = "Show"
        '
        'mnuHide
        '
        Me.mnuHide.Index = 1
        Me.mnuHide.Text = "Hide"
        '
        'lvwLibrary2
        '
        Me.lvwLibrary2.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2})
        Me.lvwLibrary2.Location = New System.Drawing.Point(8, 8)
        Me.lvwLibrary2.Name = "lvwLibrary2"
        Me.lvwLibrary2.Size = New System.Drawing.Size(272, 216)
        Me.lvwLibrary2.TabIndex = 0
        Me.lvwLibrary2.View = System.Windows.Forms.View.Details
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(216, 248)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(64, 24)
        Me.Button1.TabIndex = 1
        Me.Button1.Text = "Button1"
        '
        'scrollV
        '
        Me.scrollV.Location = New System.Drawing.Point(280, 8)
        Me.scrollV.Name = "scrollV"
        Me.scrollV.Size = New System.Drawing.Size(16, 216)
        Me.scrollV.TabIndex = 2
        '
        'ColumnHeader1
        '
        Me.ColumnHeader1.Width = 94
        '
        'ColumnHeader2
        '
        Me.ColumnHeader2.Width = 109
        '
        'SystemTray
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(320, 273)
        Me.Controls.Add(Me.scrollV)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.lvwLibrary2)
        Me.Name = "SystemTray"
        Me.Text = "SystemTray"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Public PreviousVItemCount As String
    Public TestArray(40) As ListViewItem
    Public FormLoaded As Boolean = False
    Dim OldValue As Integer = 0, ivlLodingList As Boolean = False

    Public Sub Populate()
        With lvwLibrary2
            Dim i As Integer
            Dim ColWidth As Integer
            Dim VitemCount As String

            For i = 0 To .Columns.Count - 1
                ColWidth += .Columns(i).Width
            Next

            If ColWidth > .Width Then
                VitemCount = (.Height - 39) / 14
            Else
                VitemCount = (.Height - 19) / 14
            End If

            If VitemCount.IndexOf(".") > 0 Then
                VitemCount = VitemCount.Substring(0, VitemCount.IndexOf("."))
            ElseIf VitemCount.IndexOf(".") = 0 Then
                VitemCount = 0
            End If


            If Not VitemCount = PreviousVItemCount Then
                scrollV.Maximum = TestArray.Length + 8

                If .Items.Count > 0 Then
                    .Items.Clear()
                End If

                For i = 0 To VitemCount - 1
                    Try
                        .Items.Add(TestArray(scrollV.Value + i))
                    Catch ex As Exception
                        MsgBox(ex.Message)
                    End Try
                Next
                PreviousVItemCount = VitemCount
            End If
        End With
    End Sub

    Public Sub Scroll()
        With lvwLibrary2
            If Me.lvwLibrary2.Items.Count > 0 Then
                If scrollV.Value < OldValue Then
                    .Items(.Items.Count - 1).Remove()
                    .Items.Insert(0, TestArray(scrollV.Value).Clone)
                ElseIf scrollV.Value > OldValue Then
                    .Items(0).Remove()
                    .Items.Add(TestArray(scrollV.Value).Clone)
                End If
                OldValue = scrollV.Value
            End If
        End With
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ivlLodingList = True        'initialize a variable to true so that populate() will not get reloaded on loop
        Populate()       'this works fine, only crashes when it resizes
        ivlLodingList = False
    End Sub

    Private Sub scrollV_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles scrollV.Scroll
        Scroll()
    End Sub

    Private Sub lvwLibrary2_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lvwLibrary2.SizeChanged
        If FormLoaded And ivlLodingList = False Then    'Check whether Populate() is running
            ivlLodingList = True    'initialize a variable to true so that populate() will not get reloaded on loop
            Populate()
            ivlLodingList = False
        End If
    End Sub

    Private Sub frmOptions_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Integer
        For i = 0 To 40
            Dim item As New ListViewItem
            item.Text = "test - " & i
            item.SubItems.Add("test - " & i)
            TestArray(i) = item.Clone()
        Next
        FormLoaded = True
    End Sub
End Class

Bye
Ajai
OK, here's an example. I'm assuming your ListView has two columns.  You would define a structure like this:


      Public Structure DataItem
          Public item1 As String
          Public item2 As String
      
          Public Function ToListViewItem() As ListViewItem
              Dim lvi As New ListViewItem(item1)
              lvi.SubItems.Add(item2)
              Return lvi
          End Function
      End Structure
      
Now, you would have to modify TestArray to be an array of DataItem, and change your For loop like so:

        For i = 0 To 40
            Dim item As New DataItem
            item.item1 = "test - " & i
            item.item2 = "test - " & i
            TestArray(i) = item
        Next
       
When you want to add all items in the array to the ListView, you would simply do

      For Each item as DataItem in TestArray
            lvwLibrary2.Items.Add(item.ToListViewItem)
      Next
      
This seems roundabout, but it accomplishes a few things.  First, it stores your data in a format that is both easy for you to work with and easy to convert to the display format you want.  Second, since DataItem is separate from the ListViewItem, you can do whatever you want with the ListViewItem without having to worry about whether you are changing the array.