如何在不重新插入的情况下刷新ListBox中的项目文本?

6

我有一个类 TestClass,它已经覆盖了ToString方法(它返回Name字段)。 我将TestClass的实例添加到ListBox中,在某些时候,我需要更改其中一个实例的Name,那么我该如何刷新它在ListBox中的文本呢?

using System;
using System.Windows.Forms;

namespace TestListBox
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            listBox1.Items.Add(new TestClass("asd"));
            listBox1.Items.Add(new TestClass("dsa"));
            listBox1.Items.Add(new TestClass("wqe"));
            listBox1.Items.Add(new TestClass("ewq"));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ((TestClass)listBox1.Items[0]).Name = "123";
            listBox1.Refresh(); // doesn't help
            listBox1.Update(); // same of course
        }
    }

    public class TestClass
    {
        public string Name;

        public TestClass(string name)
        {
            this.Name = name;
        }

        public override string ToString()
        {
            return this.Name;
        }
    }
}
5个回答

23

尝试

listBox1.Items[0] = listBox1.Items[0];

6

我曾遇到过同样的问题,尝试了各种不同的方法来获取项的显示文本以反映底层项目值。在查看了所有可用属性后,我发现这是最简单的方法。

lbGroupList.DrawMode = DrawMode.OwnerDrawFixed; lbGroupList.DrawMode = DrawMode.Normal;

它会触发控件内部的适当事件以更新显示的文本。


1
对于其他尝试这个的人,这个解决方案非常好用,而且与Martin的答案不同,即使您通过DataSource属性填充了列表框数据,它也可以使用。 - The Lemon

3

你的测试类需要实现INotifyPropertyChanged

public class TestClass : INotifyPropertyChanged
{
    string _name;

    public string Name
    {
        get { return _name;}
        set 
        {
              _name = value;
              _notifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void _notifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
    }

    public TestClass(string name)
    {
        this.Name = name;
    }

    public override string ToString()
    {
        return this.Name;
    }
}

然而,这仅适用于不依赖于ToString()方法而是绑定Name属性的列。

您可以通过更改代码来实现:

在类中某处声明:

BindingList<TestClass> _dataSource = new BindingList<TestClass>();

在 initializeComponent 中编写。
listBox1.DataSource = _dataSource;

然后在 _dataSource 上执行所有操作,而不是 Listbox。


2
您可以使用BindingList:
        items = new BindingList<TestClass>( );
        listBox1.DataSource = items;
        listBox1.DisplayMember = "_Name";

然后刷新列表调用:

        items.ResetBindings( );

编辑:还要别忘了为名称创建一个获取属性。
      public string _Name
    {
        get { return Name; }
        set { Name= value; }
    }

0
我使用以下代码:
public static void RefreshItemAt (ListBox listBox, int itemIndex)
{
    if (itemIndex >= 0)
    {
        Rectangle itemRect = listBox.GetItemRectangle(itemIndex);
        listBox.Invalidate(itemRect);
        listBox.Update();
    }
}

对我来说不起作用,不得不使用item = item策略。但是我喜欢这个想法。 - Jimmie Clark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接