By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,462 Members | 799 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,462 IT Pros & Developers. It's quick & easy.

Array List as DataSource For LIstBox Bug?

P: n/a
The problem is this:

I have a list box. I set an array list as the datasource. I remove an item
from the array list. I set the listbox datasource to nothing. I set the
listbox datasource to the array list again to refresh. Click on an item in
the list, and an Indexing error comes up. (in non-user code, it is trying to
get an element from the array that is greater than the number of items in the
array.)

To reproduce:

1. Create a WindowsForm Project with the following code.
2. Run the Project
3. Click on the third item in the list.
4. Click the Button (after the delete, the 'Four' item is selected)
5. Click the Button again. (after the delete, nothing is selected, but...)
6. Click on either item in the list - Error is generated.

HELP!

Thanks.

---------------------CODE to reproduce--------------------
Public Class Form1
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.
Friend WithEvents ListBox1 As System.Windows.Forms.ListBox
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.ListBox1 = New System.Windows.Forms.ListBox
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'ListBox1
'
Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Top
Me.ListBox1.Location = New System.Drawing.Point(0, 0)
Me.ListBox1.Name = "ListBox1"
Me.ListBox1.Size = New System.Drawing.Size(304, 251)
Me.ListBox1.TabIndex = 0
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(208, 264)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(72, 24)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(304, 300)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.ListBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private MyArrayList As New ArrayList

Private Class ItemClass
Implements IComparable
Private myID As Integer
Public Property ID() As Integer
Get
Return myID
End Get
Set(ByVal Value As Integer)
myID = Value
End Set
End Property
Private myValue As String
Public Property Value() As String
Get
Return myValue
End Get
Set(ByVal Value As String)
myValue = Value
End Set
End Property

Public Function CompareTo(ByVal obj As Object) As Integer Implements
System.IComparable.CompareTo
If TypeOf obj Is ItemClass Then
If DirectCast(obj, ItemClass).ID > Me.ID Then Return -1
If DirectCast(obj, ItemClass).ID < Me.ID Then Return 1
Return 0
End If
End Function
End Class

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim A As New ItemClass
A.ID = 1
A.Value = "One"
MyArrayList.Add(A)
A = New ItemClass
A.ID = 2
A.Value = "Two"
MyArrayList.Add(A)
A = New ItemClass
A.ID = 3
A.Value = "Three"
MyArrayList.Add(A)
A = New ItemClass
A.ID = 4
A.Value = "Four"
MyArrayList.Add(A)
MyArrayList.Sort()

Me.ListBox1.DataSource = MyArrayList
Me.ListBox1.ValueMember = "ID"
Me.ListBox1.DisplayMember = "Value"
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
MyArrayList.RemoveAt(2)
MyArrayList.Sort()

Me.ListBox1.DataSource = Nothing

Me.ListBox1.DataSource = MyArrayList
Me.ListBox1.ValueMember = "ID"
Me.ListBox1.DisplayMember = "Value"
End Sub
End Class

--
--Zorpie
Nov 21 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Hi Zorpie,

Did you try the listbox's refresh method?

HTH,

Bernie Yaeger

"Zorpiedoman" <no*********@beatles.com> wrote in message
news:8E**********************************@microsof t.com...
The problem is this:

I have a list box. I set an array list as the datasource. I remove an
item
from the array list. I set the listbox datasource to nothing. I set the
listbox datasource to the array list again to refresh. Click on an item
in
the list, and an Indexing error comes up. (in non-user code, it is trying
to
get an element from the array that is greater than the number of items in
the
array.)

To reproduce:

1. Create a WindowsForm Project with the following code.
2. Run the Project
3. Click on the third item in the list.
4. Click the Button (after the delete, the 'Four' item is selected)
5. Click the Button again. (after the delete, nothing is selected,
but...)
6. Click on either item in the list - Error is generated.

HELP!

Thanks.

---------------------CODE to reproduce--------------------
Public Class Form1
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.
Friend WithEvents ListBox1 As System.Windows.Forms.ListBox
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.ListBox1 = New System.Windows.Forms.ListBox
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'ListBox1
'
Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Top
Me.ListBox1.Location = New System.Drawing.Point(0, 0)
Me.ListBox1.Name = "ListBox1"
Me.ListBox1.Size = New System.Drawing.Size(304, 251)
Me.ListBox1.TabIndex = 0
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(208, 264)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(72, 24)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(304, 300)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.ListBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private MyArrayList As New ArrayList

Private Class ItemClass
Implements IComparable
Private myID As Integer
Public Property ID() As Integer
Get
Return myID
End Get
Set(ByVal Value As Integer)
myID = Value
End Set
End Property
Private myValue As String
Public Property Value() As String
Get
Return myValue
End Get
Set(ByVal Value As String)
myValue = Value
End Set
End Property

Public Function CompareTo(ByVal obj As Object) As Integer
Implements
System.IComparable.CompareTo
If TypeOf obj Is ItemClass Then
If DirectCast(obj, ItemClass).ID > Me.ID Then Return -1
If DirectCast(obj, ItemClass).ID < Me.ID Then Return 1
Return 0
End If
End Function
End Class

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim A As New ItemClass
A.ID = 1
A.Value = "One"
MyArrayList.Add(A)
A = New ItemClass
A.ID = 2
A.Value = "Two"
MyArrayList.Add(A)
A = New ItemClass
A.ID = 3
A.Value = "Three"
MyArrayList.Add(A)
A = New ItemClass
A.ID = 4
A.Value = "Four"
MyArrayList.Add(A)
MyArrayList.Sort()

Me.ListBox1.DataSource = MyArrayList
Me.ListBox1.ValueMember = "ID"
Me.ListBox1.DisplayMember = "Value"
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
MyArrayList.RemoveAt(2)
MyArrayList.Sort()

Me.ListBox1.DataSource = Nothing

Me.ListBox1.DataSource = MyArrayList
Me.ListBox1.ValueMember = "ID"
Me.ListBox1.DisplayMember = "Value"
End Sub
End Class

--
--Zorpie

Nov 21 '05 #2

P: n/a
That does not refresh the data. The work-around so far is to Set the
SelectedIndex to -1 BEFORE removing the item from the arraylist. Then it
works fine, but this may not always be possible in real life.

-zorpy

"Bernie Yaeger" wrote:
Hi Zorpie,

Did you try the listbox's refresh method?

HTH,

Bernie Yaeger

Nov 21 '05 #3

P: n/a

"Zorpiedoman" <no*********@beatles.com> wrote
The problem is this:

I have a list box. I set an array list as the datasource. I remove an item
from the array list. I set the listbox datasource to nothing. I set the
listbox datasource to the array list again to refresh. Click on an item in
the list, and an Indexing error comes up.
Everywhere you have
Me.ListBox1.DataSource = MyArrayList
Use:
Me.ListBox1.DataSource = MyArrayList.Clone

HTH
LFS

Nov 21 '05 #4

P: n/a

"Dennis" <De****@discussions.microsoft.com> wrote
Interesting! What is the logic (why does this work)? Any idea?


It may be that binding is an expensive operation such that they
included a test to see if the new object is the same as the old
object, and return early if they were the same.

So even though you changed the array, you assign the same
arraylist back to the DataSource property, which gets detected
as the same object as before. Since its the same object, they
skip tring to bind to it, because it is already bound to...

That is only my speculation.
LFS
Nov 21 '05 #5

P: n/a
Thanks Larry. It would be like Microsoft to think they know better than us
what we want to do.

"Larry Serflaten" wrote:

"Dennis" <De****@discussions.microsoft.com> wrote
Interesting! What is the logic (why does this work)? Any idea?


It may be that binding is an expensive operation such that they
included a test to see if the new object is the same as the old
object, and return early if they were the same.

So even though you changed the array, you assign the same
arraylist back to the DataSource property, which gets detected
as the same object as before. Since its the same object, they
skip tring to bind to it, because it is already bound to...

That is only my speculation.
LFS

Nov 21 '05 #6

P: n/a
However, my setting .datasource = nothing, then re-setting it to the array
list does the same thing, so this does not fix the problem.
Nov 21 '05 #7

P: n/a
This is a rather costly solution... also, if any docking is being used, you
have just changed the z-order of the control and it could appear in an
unwanted place on the form. why do you think this would change anything
anyway?

"Cor Ligthert" wrote:
Zorpiedoman,

In my opinion is this as you wrote a bug, try this
\\\
MyArrayList.RemoveAt(2)
MyArrayList.Sort()
Me.Controls.Remove(ListBox1)
Me.Controls.Add(ListBox1)
///
Than it works as it should work in my opinion without that remove and add.

I hope this gives an idea

Cor

Nov 21 '05 #8

P: n/a
> This is a rather costly solution... also, if any docking is being used,
you
have just changed the z-order of the control and it could appear in an
unwanted place on the form. why do you think this would change anything
anyway?


Because I tried it.

Cor
Nov 21 '05 #9

P: n/a
Do you see my point, however, that this is not a viable solution?

"Cor Ligthert" wrote:
This is a rather costly solution... also, if any docking is being used,
you
have just changed the z-order of the control and it could appear in an
unwanted place on the form. why do you think this would change anything
anyway?


Because I tried it.

Cor

Nov 21 '05 #10

P: n/a
Zorpiedoman,

I told that it is in my opinion as well a bug, however I don't see your
problem. Do you really manage the order of the controls in the control
collection, I never saw that somebody do (except for the tabcontrol).

This means removing an reference of an object and adding it again, maybe it
does not even repaint, however my eyes are not that fast, maybe you can see
it..(This is as well used to overcome the tabcontrol bug by the way)

And with that not saying that it is a nice solution.

Cor
Nov 21 '05 #11

P: n/a

"Zorpiedoman" <no*********@beatles.com> wrote
However, my setting .datasource = nothing, then re-setting it to the array
list does the same thing, so this does not fix the problem.


Add a debug statement to the DataSourceChanged event and try them
both again. If that event does not fire, then the datasource has not changed
and no refresh of the data happens. You'll note that using the Clone, as
suggested, does cause that event to happen....

LFS
Nov 21 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.