Solved

items.clear not working to clear listview?

Posted on 2004-09-29
4
270 Views
Last Modified: 2010-08-05
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

---------------------------------------------------------------------------------------------------------------
0
Comment
Question by:gozza11
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 2

Accepted Solution

by:
GohdanTheMoblin earned 500 total points
ID: 12186250
I'd like to know what line your code is crashing at, but here's my guess:

A ListViewItem is a reference type.  When you add item to TestArray(i), you are only adding a reference to the item.  When you call .Items.Clear(), you destroy the object that both the ListView and TestArray referenced, so now TestArray is an array of 41 (stupid VB array syntax means your array has 0 through 40 = 41 elements) references to Nothing.

This problem could be solved by changing the last line of the For loop in the Load handler to:
TestArray(i) = item.Clone()

Although for lots of ListViewItems this could get expensive.  The way I handle situations like this is to create a class that has a member for each item, and a method that returns a ListViewItem properly initialized.  This way, you keep an array of these objects, and you don't have to worry about cloning.
0
 

Author Comment

by:gozza11
ID: 12186786
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
0
 
LVL 11

Expert Comment

by:ajaikumarr
ID: 12187322
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
0
 
LVL 2

Expert Comment

by:GohdanTheMoblin
ID: 12187350
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.
0

Featured Post

[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
In this video, viewers are given an introduction to using the Windows 10 Snipping Tool, how to quickly locate it when it's needed and also how make it always available with a single click of a mouse button, by pinning it to the Desktop Task Bar. Int…

622 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question