如何解决在 VB 中更改 ListBox 时,ToString 不更新对象
我有一个表单可以更改列表框中的类的内容。信息已正确更新,但我的对象上的 ToString 覆盖不会刷新 - 这意味着旧的 ToString 不会更改。我该如何解决这个问题?
这是我的对象:
Public Class Destination
Public strDestinationName As String
Public strAddress As String
Public intQuality As Integer
Public intPrice As Integer
Public Overrides Function ToString() As String
Return strDestinationName
End Function
End Class
这是应该更新的代码
Dim selectedDestination As Destination
selectedDestination = CType(ListForm.lbNames.SelectedItem,Destination)
selectedDestination.strDestinationName = tbName.Text
selectedDestination.strAddress = tbAddress.Text
selectedDestination.intPrice = cbPrice.SelectedIndex
selectedDestination.intQuality = cbQuality.SelectedIndex
Me.Close()
解决方法
无论您如何向 ListBox
添加项目,实际显示数据的是 ListBox
。在您的情况下,鉴于 Destination
是 ListBox
对象,您似乎以某种方式将 SelectedItem
对象添加到 Destination
中。鉴于您已经编写了该 ToString
方法,您大概依赖它来生成 ListBox
为每个项目显示的文本。您现在希望能够更改其中一项的 strDestinationName
字段的值,并让 ListBox
反映该更改。您认为这会如何发生?
必须调用 ToString
方法才能获得新值,您认为谁会调用它?调用它的将是 ListBox
,因为它是显示结果的 ListBox
。当您更改该字段时,您希望 ListBox
调用您的 ToString
方法,但它为什么会这样做? ListBox
必须调用该方法的原因是什么?它不知道您所做的更改,为什么它会认为必须获取新数据?
解决您的问题的方法是以某种方式更改您的代码,以通知 ListBox
数据已更改,以便它知道需要获取新数据并显示它。有多种方法可以做到这一点。
最简单的选择是通过 ListBox
将您的数据绑定到 BindingSource
,然后,当您修改项目时,调用 ResetItem
方法或 {{1} 的类似方法}}。这将引发由 BindingSource
处理的事件,然后 ListBox
知道它需要刷新该项目的数据。这就是提示 ListBox
调用您的 ListBox
方法并获取要显示的新数据的原因。您可以将 ToString
添加到设计器中的表单中,然后在您当前添加项目的位置进行绑定,例如
BindingSource
修改看起来像这样:
Dim destinations As New List(Of Destination)
For i = 1 To 10
Dim d As New Destination
d.strDestinationName = "Destination " & i
destinations.Add(d)
Next
destinationBindingSource.DataSource = destinations
destinationListBox.DataSource = destinationBindingSource
Dim selectedDestination = DirectCast(destinationBindingSource.Current,Destination)
selectedDestination.strDestinationName = "New Destination"
destinationBindingSource.ResetCurrentItem()
属性返回当前在绑定 UI 中选择的项目,Current
方法通知绑定 UI 刷新该项目的显示。
这确实不是最好的方法,因为您可以控制项目类型。您应该做的是使用属性而不是字段来实现类型,摆脱只返回一个属性值的 ResetCurrentItem
方法,然后向该属性添加更改事件:
ToString
您现在可以直接绑定 Public Class Destination
Private _destinationName As String
Public Property DestinationName As String
Get
Return _destinationName
End Get
Set(value As String)
If _destinationName <> value Then
_destinationName = value
OnDestinationNameChanged(EventArgs.Empty)
End If
End Set
End Property
Public Property Address As String
Public Property Quality As Integer
Public Property Price As Integer
Public Event DestinationNameChanged As EventHandler
Protected Overridable Sub OnDestinationNameChanged(e As EventArgs)
RaiseEvent DestinationNameChanged(Me,e)
End Sub
End Class
对象列表并将其中任何属性指定为 Destination
以显示该属性值:
DisplayMember
您不需要 Dim destinations As New List(Of Destination)
For i = 1 To 10
Dim d As New Destination
d.strDestinationName = "Destination " & i
destinations.Add(d)
Next
destinationListBox.DisplayMember = "DestinationName"
destinationListBox.DataSource = destinations
方法,因为 ToString
指定应显示具有该名称的属性的值。当您修改项目的 DisplayMember
属性值时,它会引发 DestinationName
事件并通知 DestinationNameChanged
它需要刷新该项目的显示,因此您不需要任何额外的代码来更新 ListBox
。
如果您只打算修改现有项目,那很好。如果您想在绑定后添加和/或删除项目,仍然存在问题。在此示例中,用于将项目绑定到控件的 ListBox
类没有任何事件来通知控件对列表的更改。在这种情况下,您可以根据需要再次使用 BindingSource。如果您通过 List(Of T)
添加和删除项目,那么它将引发相应的事件并且 BindingSource
将更新。如果您想通过基础列表添加和删除,则必须在进行更改时调用 ListBox
的适当方法。
另一种方法是使用 BindingSource
而不是 BindingList(Of Destination)
。顾名思义,List(Of Destination)
类用于绑定,因此当列表更改时,它会自动引发适当的事件,以使 UI 无需额外代码即可更新。使用项目类中的属性更改事件和 BindingList(Of T)
的组合,您可以添加、编辑和删除绑定列表中的项目,UI 将自动反映这些更改。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。