如何使ListBox刷新其项目文本?

我为一个还没有意识到像ListBox这样的ListBox不需要包含string的人举个例子, 他一直在存储格式化的string,并通过复杂的parsing箍跳转,以获取数据的ListBox ,我想告诉他有一个更好的方法。

我注意到,如果我有一个对象存储在ListBox然后更新影响ToString的值, ListBox不会自我更新。 我已经尝试调用控件上的RefreshUpdate ,但都不起作用。 下面是我正在使用的示例的代码,它需要您将一个列表框和一个button拖到窗体上:

 Public Class Form1 Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) MyBase.OnLoad(e) For i As Integer = 1 To 3 Dim tempInfo As New NumberInfo() tempInfo.Count = i tempInfo.Number = i * 100 ListBox1.Items.Add(tempInfo) Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click For Each objItem As Object In ListBox1.Items Dim info As NumberInfo = DirectCast(objItem, NumberInfo) info.Count += 1 Next End Sub End Class Public Class NumberInfo Public Count As Integer Public Number As Integer Public Overrides Function ToString() As String Return String.Format("{0}, {1}", Count, Number) End Function End Class 

我认为也许问题是使用字段,并尝试实施INotifyPropertyChanged ,但这没有效果。 (我使用字段的原因是因为这是一个例子,我不想添加几十条与我正在演示的主题无关的行。)

老实说,我从来没有尝试像这样更新项目之前, 在过去,我一直在添加/删除项目,而不是编辑它们。 所以我从来没有注意到我不知道如何做这个工作。

那么我错过了什么?

BindingList处理自己更新绑定。

 using System; using System.ComponentModel; using System.Windows.Forms; namespace TestBindingList { public class Employee { public string Name { get; set; } public int Id { get; set; } } public partial class Form1 : Form { private BindingList<Employee> _employees; private ListBox lstEmployees; private TextBox txtId; private TextBox txtName; private Button btnRemove; public Form1() { InitializeComponent(); FlowLayoutPanel layout = new FlowLayoutPanel(); layout.Dock = DockStyle.Fill; Controls.Add(layout); lstEmployees = new ListBox(); layout.Controls.Add(lstEmployees); txtId = new TextBox(); layout.Controls.Add(txtId); txtName = new TextBox(); layout.Controls.Add(txtName); btnRemove = new Button(); btnRemove.Click += btnRemove_Click; btnRemove.Text = "Remove"; layout.Controls.Add(btnRemove); Load+=new EventHandler(Form1_Load); } private void Form1_Load(object sender, EventArgs e) { _employees = new BindingList<Employee>(); for (int i = 0; i < 10; i++) { _employees.Add(new Employee() { Id = i, Name = "Employee " + i.ToString() }); } lstEmployees.DisplayMember = "Name"; lstEmployees.DataSource = _employees; txtId.DataBindings.Add("Text", _employees, "Id"); txtName.DataBindings.Add("Text", _employees, "Name"); } private void btnRemove_Click(object sender, EventArgs e) { Employee selectedEmployee = (Employee)lstEmployees.SelectedItem; if (selectedEmployee != null) { _employees.Remove(selectedEmployee); } } } } 

当我需要更新列表框时,我使用这个类。

更新列表中的对象,然后调用其中一个包含的方法,具体取决于索引是否可用。 如果要更新列表中包含的对象,但没有索引,则必须调用RefreshItems并更新所有项目。

 public class RefreshingListBox : ListBox { public new void RefreshItem(int index) { base.RefreshItem(index); } public new void RefreshItems() { base.RefreshItems(); } } 
 lstBox.Items[lstBox.SelectedIndex] = lstBox.SelectedItem; 
 typeof(ListBox).InvokeMember("RefreshItems", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, myListBox, new object[] { }); 

在数据源和列表框的数据源属性之间使用datasource属性和BindingSource对象。 然后刷新。

更新添加示例。

像这样:

 Public Class Form1 Private datasource As New List(Of NumberInfo) Private bindingSource As New BindingSource Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) MyBase.OnLoad(e) For i As Integer = 1 To 3 Dim tempInfo As New NumberInfo() tempInfo.Count = i tempInfo.Number = i * 100 datasource.Add(tempInfo) Next bindingSource.DataSource = datasource ListBox1.DataSource = bindingSource End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click For Each objItem As Object In datasource Dim info As NumberInfo = DirectCast(objItem, NumberInfo) info.Count += 1 Next bindingSource.ResetBindings(False) End Sub End Class Public Class NumberInfo Public Count As Integer Public Number As Integer Public Overrides Function ToString() As String Return String.Format("{0}, {1}", Count, Number) End Function End Class 

如果从ListBox派生,则可以调用RefreshItem保护的方法。 只要在你自己的types中重新公开这个方法。

 public class ListBox2 : ListBox { public void RefreshItem2(int index) { RefreshItem(index); } } 

然后改变你的devise器文件使用你自己的types(在这种情况下,ListBox2)。

这有点不专业,但它的作品。 我刚刚删除并添加该项目(也再次select它)。 该列表根据“显示和更改”属性进行sorting,对我来说也是如此。 副作用是增加了事件(索引改变)。

 if (objLstTypes.SelectedItem != null) { PublisherTypeDescriptor objType = (PublisherTypeDescriptor)objLstTypes.SelectedItem; objLstTypes.Items.Remove(objType); objLstTypes.Items.Add(objType); objLstTypes.SelectedItem = objType; } 

如果您使用如下的绘图方法:

 private void listBox1_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); e.DrawFocusRectangle(); Sensor toBeDrawn = (listBox1.Items[e.Index] as Sensor); e.Graphics.FillRectangle(new SolidBrush(toBeDrawn.ItemColor), e.Bounds); e.Graphics.DrawString(toBeDrawn.sensorName, new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold), new SolidBrush(Color.White),e.Bounds); } 

传感器是我的课程。

所以,如果我在某处更改Color类,则可以简单地将其更新为:

 int temp = listBoxName.SelectedIndex; listBoxName.SelectedIndex = -1; listBoxName.SelectedIndex = temp; 

Color将更新,只是另一种解决scheme:)

我不太了解vb.net,但在C#中,您应该使用数据源,然后通过调用listbox.bind()来绑定它。

如果objLstTypes是您的ListBox名称使用objLstTypes.Items.Refresh(); 希望这个作品…