44

我正在为尚未意识到控件之类的控件ListBox不必包含字符串的人举个例子;他一直在存储格式化的字符串并跳过复杂的解析箍以将数据从其中取出,ListBox我想向他展示有更好的方法。

我注意到,如果我有一个对象存储在ListBoxthen 更新一个影响 的值,ToStringListBox不会更新自身。我试过打电话RefreshUpdate控制,但都不管用。这是我正在使用的示例的代码,它需要您将列表框和按钮拖到表单上:

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,但这没有效果。(我使用字段的原因是因为它是一个示例,我不想添加与我正在演示的主题无关的几十行。)

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

那么我错过了什么?

4

10 回答 10

34

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

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

public class RefreshingListBox : ListBox
{
    public new void RefreshItem(int index)
    {
        base.RefreshItem(index);
    }

    public new void RefreshItems()
    {
        base.RefreshItems();
    }
}
于 2008-09-14T23:27:51.993 回答
29
lstBox.Items[lstBox.SelectedIndex] = lstBox.SelectedItem;
于 2010-11-26T14:06:50.787 回答
25

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);
            }
        }
    }
}
于 2010-01-25T20:09:43.900 回答
16
typeof(ListBox).InvokeMember("RefreshItems", 
  BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
  null, myListBox, new object[] { });
于 2011-01-08T00:02:04.513 回答
9

在数据源和列表框的数据源属性之间使用数据源属性和 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
于 2008-09-14T15:49:27.040 回答
2

如果您从 ListBox 派生,则可以调用 RefreshItem 受保护的方法。只需在您自己的类型中重新公开此方法即可。

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

然后更改您的设计器文件以使用您自己的类型(在本例中为 ListBox2)。

于 2008-09-14T23:05:34.153 回答
0

这有点不专业,但它确实有效。我刚刚删除并添加了该项目(也再次选择了它)。该列表是根据“显示和更改”属性排序的,所以对我来说也很好。副作用是引发了额外的事件(索引更改)。

if (objLstTypes.SelectedItem != null)
{
 PublisherTypeDescriptor objType = (PublisherTypeDescriptor)objLstTypes.SelectedItem;
 objLstTypes.Items.Remove(objType);
 objLstTypes.Items.Add(objType);
 objLstTypes.SelectedItem = objType;
}
于 2009-05-30T19:03:43.827 回答
0

如果您使用如下绘制方法:

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将更新,只是另一种解决方案:)

于 2015-03-12T11:05:30.510 回答
-1

我对 vb.net 了解不多,但在 C# 中你应该使用数据源,然后通过调用绑定它就listbox.bind()可以了。

于 2008-09-14T17:00:12.393 回答
-3

如果 objLstTypes 是您的 ListBox 名称使用 objLstTypes.Items.Refresh(); 希望这有效...

于 2009-06-14T20:06:26.900 回答