我有一个绑定到列表的列表框是一个类。一切正常,直到我尝试将新项目添加到列表中。在此过程中,数据源设置为无需刷新列表,并且显然是“刷新”。没有做到。列表得到刷新,绑定到列表框数据的其他控件显示列表在那里并且是正确的但是列表显示为空,尽管它显示滚动条。我试图改变字体颜色,以防万一..没什么!
有人知道为什么会这样吗?怎么解决?还是更好的刷新方法?
代码:
Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click
'lbNames is the listbox carrying all the data
Dim oContacts As List(Of clsContact) = lbNames.DataSource
lbNames.DataSource = Nothing
'Build the new Item, add it to the collection
Dim oNewCont As New clsContact
oNewCont.Editable = True
oNewCont.IsActive = True
oNewCont.Firstname = "Jimmy"
oNewCont.Lastname = "Smith"
oContacts.Add(oNewCont)
lbNames.Refresh()
' Re-Set up Autocomplete text box
Dim MySource As New AutoCompleteStringCollection()
For Each oc As clsContact In oContacts
MySource.Add(oc.FullName)
Next
txtName.AutoCompleteMode = AutoCompleteMode.Suggest
txtName.AutoCompleteCustomSource = MySource
txtName.AutoCompleteSource = AutoCompleteSource.CustomSource
'Set List Box data back to the collection
lbNames.DataSource = oContacts
lbNames.DisplayMember = "FullName"
End Sub
首发加载:
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim oCont As List(Of clsContact)
lbNames.DrawMode = DrawMode.OwnerDrawVariable
Dim oTypes As List(Of clsPhoneType) = loadTypes()
cboPhoneType.DataSource = oTypes
cboPhoneType.DisplayMember = "Type"
cboPhoneType.ValueMember = "ID"
oCont = LoadNames()
lbNames.DataSource = oCont
lbNames.DisplayMember = "FullName"
Dim MySource As New AutoCompleteStringCollection()
For Each oc As clsContact In oCont
MySource.Add(oc.FullName)
Next
txtName.AutoCompleteMode = AutoCompleteMode.Suggest
txtName.AutoCompleteCustomSource = MySource
txtName.AutoCompleteSource = AutoCompleteSource.CustomSource
End Sub
Private Sub lbNames_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles lbNames.DrawItem
e.DrawBackground()
Dim textBrush As Brush = Brushes.Black
Dim drawFont As System.Drawing.Font = e.Font
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
e.Graphics.FillRectangle(Brushes.WhiteSmoke, e.Bounds)
End If
Dim oCont As clsContact = DirectCast(sender, System.Windows.Forms.ListBox).Items(e.Index)
If oCont.IsActive Then
textBrush = Brushes.Black
If oCont.IsDirty Then textBrush = Brushes.LightCoral
Else
textBrush = Brushes.LightGray
End If
Dim str = oCont.FullName
e.Graphics.DrawString(str, e.Font, textBrush, e.Bounds, StringFormat.GenericDefault)
e.DrawFocusRectangle()
End Sub
答案 0 :(得分:0)
您使用了错误的工具。 List(Of T)并未提出任何事件。当绑定到控件时,控件不知道是否添加/移除/移动了任何项目。幸运的是,BindingList(Of T)来救援。每当修改列表时,它都会引发ListChanged事件。作为奖励,如果您的类/模型实现INotifyPropertyChanged接口,则控件也将反映属性更改。
lbNames.DataSource = New BindingList(Of clsContact)(oCont)
这是一个示例表单,向您展示基础知识:
Imports System.ComponentModel
Public Class Form1
Public Sub New()
Me.InitializeComponent()
Me.btnAdd = New Button With {.TabIndex = 0, .Dock = DockStyle.Top, .Height = 30, .Text = "Add new contact"}
Me.btnChange = New Button With {.TabIndex = 1, .Dock = DockStyle.Top, .Height = 30, .Text = "Change random contact name"}
Me.lbContacts = New ListBox With {.TabIndex = 2, .Dock = DockStyle.Fill}
Me.Controls.AddRange({Me.lbContacts, Me.btnChange, Me.btnAdd})
End Sub
Private Sub HandleMeLoad(sender As Object, e As EventArgs) Handles Me.Load
Dim list As New List(Of Contact)
For i As Integer = 1 To 10
list.Add(New Contact With {.Name = String.Format("Contact # {0}", i)})
Next
Me.lbContacts.DataSource = New BindingList(Of Contact)(list)
Me.lbContacts.DisplayMember = "Name"
End Sub
Private Sub HandleButtonAddClick(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim list As BindingList(Of Contact) = DirectCast(Me.lbContacts.DataSource, BindingList(Of Contact))
list.Add(New Contact With {.Name = String.Format("Contact # {0}", (list.Count + 1))})
End Sub
Private Sub HandleButtonChangeClick(sender As Object, e As EventArgs) Handles btnChange.Click
Static rnd As New Random()
Dim list As BindingList(Of Contact) = DirectCast(Me.lbContacts.DataSource, BindingList(Of Contact))
If (list.Count > 0) Then
With list.Item(rnd.Next(0, list.Count))
.Name = Guid.NewGuid().ToString()
End With
End If
End Sub
Public Class Contact
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Property Name As String
Get
Return Me.m_name
End Get
Set(value As String)
If (value <> Me.m_name) Then
Me.m_name = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Name"))
End If
End Set
End Property
Private m_name As String
End Class
Private WithEvents btnAdd As Button
Private WithEvents btnChange As Button
Private WithEvents lbContacts As ListBox
End Class
答案 1 :(得分:0)
似乎解决这个问题的方法是将drawmode翻转回正常状态。 添加: lbNames.DrawMode = DrawMode.Normal lbNames.DrawMode = DrawMode.OwnerDrawVariable 解决了这个问题。
我想正在发生的事情是绘图处理程序由于某种原因而变得断开连接,因此在附加数据源时不会重绘列表的竞争。
我的新工作代码: Private Sub btnNew_Click(sender as Object,e As EventArgs)处理btnNew.Click
'lbNames is the listbox carrying all the data
Dim oContacts As List(Of clsContact) = lbNames.DataSource
lbNames.DataSource = Nothing
'Build the new Item, add it to the collection
Dim oNewCont As New clsContact
oNewCont.Editable = True
oNewCont.IsActive = True
oNewCont.Firstname = "Jimmy"
oNewCont.Lastname = "Smith"
oContacts.Add(oNewCont)
' Re-Set up Autocomplete text box
Dim MySource As New AutoCompleteStringCollection()
For Each oc As clsContact In oContacts
MySource.Add(oc.FullName)
Next
txtName.AutoCompleteMode = AutoCompleteMode.Suggest
txtName.AutoCompleteCustomSource = MySource
txtName.AutoCompleteSource = AutoCompleteSource.CustomSource
'Set List Box data back to the collection
lbNames.DataSource = oContacts
lbNames.DisplayMember = "FullName"
lbNames.DrawMode = DrawMode.Normal
lbNames.DrawMode = DrawMode.OwnerDrawVariable
End Sub