Can ListBox.DisplayMember values be refreshed?

omegagames

New member
Joined
Jun 20, 2007
Messages
2
Programming Experience
3-5
To demonstrate my problem, I've just ripped off of the sample program here:
http://msdn2.microsoft.com/en-us/library/system.windows.forms.listcontrol.displaymember.aspx


Basically, an arraylist is created and values are added to it. Then the ListBox's DataSource is set to it and the DisplayMember is set to LongName.

I added a button, which when clicked, appends some text ("***") to the end of long name (I made the property read/write). When the ListBox is clicked, the TextBox naturally calls the property and gets the correct value, but since the DisplayMember strings seem to only be retrieved once, there is no way to display the changed text.

VB.NET:
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Collections

Public Class USState
    Private myShortName As String
    Private myLongName As String

    Public Sub New(ByVal strLongName As String, ByVal strShortName As String)
        Me.myShortName = strShortName
        Me.myLongName = strLongName
    End Sub 'New

    Public ReadOnly Property ShortName() As String
        Get
            Return myShortName
        End Get
    End Property

    Public Property LongName() As String
        Set(ByVal value As String)
            myLongName = value
        End Set
        Get
            Return myLongName
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return Me.ShortName + " - " + Me.LongName
    End Function 'ToString
End Class 'USState


Public Class ListBoxSample3
    Inherits Form
    Private ListBox1 As New ListBox()
    Private textBox1 As New TextBox()
    Private WithEvents btn As New Button()
    Dim USStates As New ArrayList()

    Public Sub New()
        Me.ClientSize = New Size(292, 190)
        Me.Text = "ListBox Sample3"
        ListBox1.Location = New Point(24, 16)
        ListBox1.Name = "ListBox1"
        ListBox1.Size = New Size(240, 90)
        textBox1.Location = New Point(24, 160)
        textBox1.Name = "textBox1"
        textBox1.Size = New Size(240, 24)
        btn.Size = New Size(60, 25)
        btn.Location = New Point(204, 110)
        btn.Text = "Change"
        Me.Controls.AddRange(New Control() {ListBox1, textBox1, btn})

        ' Populates the list box using DataSource. 
        ' DisplayMember is used to display just the long name of each state.
        USStates.Add(New USState("Alabama", "AL"))
        USStates.Add(New USState("Washington", "WA"))
        USStates.Add(New USState("West Virginia", "WV"))
        USStates.Add(New USState("Wisconsin", "WI"))
        USStates.Add(New USState("Wyoming", "WY"))
        AddHandler ListBox1.SelectedValueChanged, AddressOf ListBox1_SelectedValueChanged
        ListBox1.DataSource = USStates
        ListBox1.DisplayMember = "LongName"
    End Sub 'New

    Private Sub InitializeComponent()

    End Sub 'InitializeComponent

    Private Sub ListBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs)
        If ListBox1.SelectedIndex <> -1 Then
            textBox1.Text = ListBox1.SelectedValue.ToString()
        End If
    End Sub 'ListBox1_SelectedValueChanged

    Private Sub btn_clicked(ByVal sender As Object, ByVal e As EventArgs) Handles btn.Click
        CType(USStates(ListBox1.SelectedIndex), USState).LongName &= "***"
    End Sub
End Class 'ListBoxSample3


As of now I'm calling DisplayMember twice, once to clear it, and again to reset it (which causes the list box to reset the text strings displayed. This is a dirty work-around, IMO, and I feel like there should be some way to accomplish this... any ideas?
 
Your problem is that the ArrayList doesn't raise any events when the list changes to notify the bound control that it should refresh its display. You should use a BindingList(Of USState) rather than an ArrayList because the BindingList has functionality specifically designed to support data-binding. If the items in the list have the appropriate functionality everything will happen automatically, but you have to implement that functionality in your classes. If you don't want to do that then simply call the BindingList's ResetBindings or ResetItem methods in order to notify the bound control that it should refresh.

Note also that you should not use the ArrayList class anyway, even if not binding. You should use the generic List class, which provides the same functionality as the ArrayList but adds type-safety. In your case you'd use a List(Of USState) in general but because this you're using data-binding you use the BindingList(Of USState) instead. It is also a generic collection and thus provides the same type-safety.
 
Thank you for your reply.

Again, that wasn't my code, what I'm doing is very similar but I don't use the ArrayList like that. I will look into the BindingList for my application though. Thanks for pointing that out to me!
 
Back
Top