Forcing Listbox items to redraw - HOW?

L

larrylard

Searching google groups for 'listbox items redraw' yields lots of
people with the same problem, but little in the way of solutions.

The problem: A ListBox's Items collection can contain arbitrary
objects, which is wonderful, and the listbox will decide what to
display for each item by calling its ToString. This means we don't need
Tags, we don't need ItemData, all great.

However.

When one of those Item object changes in such a way that its ToString
changes - there is apparently NO WAY to tell the listbox about this.

Example:

Public Class SomeClass
Public SomeData As Double

Public Sub New()

End Sub

Public Sub New(ByVal d As Double)
Me.SomeData = d
End Sub

Public Overrides Function ToString() As String
Dim a() As Char = SomeData.ToString.ToCharArray
Array.Reverse(a)
Return New String(a)
End Function
End Class

A straightforward demonstration class with a ToString that depends on
internal state. Yes I know public members are bad. This is an example
:)

Create a form, put a listbox ListBox1 on it, and three Buttons, Button1
Button2 Button3. In the form:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
With ListBox1.Items
.Clear()
.Add(New SomeClass(3.45#))
.Add(New SomeClass(4.435345#))
.Add(New SomeClass(Math.PI))
End With
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Dim o As SomeClass = DirectCast(ListBox1.Items(1), SomeClass)
o.SomeData *= 2

'WHAT NOW?
ListBox1.Refresh()
ListBox1.Invalidate()
ListBox1.Update()
'none of the above have any effect
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim al As ArrayList = New ArrayList

For Each o As Object In ListBox1.Items
al.Add(o)
Next

With ListBox1.Items
.Clear()
For Each o As Object In al
.Add(o)
Next
End With

End Sub


When you run this, click Button1 to have some SomeClass's put into the
list box. When you click Button2, one of those SomeClass's *changes*
and its ToString changes too, but (as you will see), .Refresh,
..Invalidate, .Update - all fail to persude the listbox to go get the
ToString again.

Button3 removes then adds back all the items in the list box - this
DOES force the listbox to check their ToString's, and enables you to
see the updated SomeClass.

Removing and restoring the single affected SomeClass also works, but
with rather unpleasant side effects on ordering, selectedness, etc etc.

So, any bright ideas as to how to tell the listbox that one of its
Item's ToString has changed? Remember, these DON'T work:

..Refresh
..Update
..Invalidate
 
M

Morten Wennevik

Hi Larry,

As far as I know you need to remove and reattach the item. The ListBox appears to have some internal string list it uses for redrawing and this list isn't updated even though the item changes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top