如何使用INotifyPropertyChanged更新ListBox的项目

3
我有一个列表框,它绑定了一个对象集合。我想修改显示方式,以向用户展示这些对象中的哪一个是程序中的“START”对象。
我尝试了以下方法,但列表框没有自动更新。无效化控件也没有用。
我唯一能找到的方法是完全删除数据绑定,然后再次添加。但在我的情况下,这并不理想。
还有其他方法吗?
class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _name;
    public string Name
    {
        get
        {
            if (PersonManager.Instance.StartPerson == this)
                return _name + " (Start)";                      
            return _name;
        }
        set
        {
            _name = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Name"));
        }
    }

    public Person(string name)
    {
        Name = name;
    }
}

这是管理列表和起始项的类。
class PersonManager
{
    public BindingList<Person> persons { get; set; }
    public Person StartPerson { get; set; }

    private static PersonManager _instance;
    public static PersonManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new PersonManager();
            }
            return _instance;
        }
    }

    private PersonManager()
    {
        persons = new BindingList<Person>();
    }
}

在表单中,我使用以下代码
    private void button1_Click(object sender, EventArgs e)
    {
        PersonManager.Instance.StartPerson = (Person)listBox1.SelectedItem;
    }
1个回答

3
我非常确定问题的原因是,当您这样做时,实际上会使Person.Name属性的“获取”访问器更改值(并在UI方面像设置访问器一样运行)。
然而,没有任何内容更新绑定以表明正在发生这种情况。如果在设置start时调用了PropertyChanged,则我认为它会更新。
这很笨拙,但是按照您编写的方式,我相信您可以添加此内容并使其正常工作(注意:我没有测试过,所以可能存在问题)。
private void button1_Click(object sender, EventArgs e)
{
    Person newStart = (Person)listBox1.SelectedItem;
    if (newStart != null)
    {
        PersonManager.Instance.StartPerson = newStart;
        newStart.Name = newStart.Name; // Dumb, but forces a PropertyChanged event so the binding updates
    }
}

非常感谢您的快速回复,这个方法非常有效! - Sjors Miltenburg
只是好奇,如果您从头开始编写代码,您会如何解决这个问题? - Sjors Miltenburg
一种可能更清晰的方式是拥有类似于名称+显示名称属性的东西。或者,如果您有一个属性来确定一个人是否是“开始”人,设置它将引发事件。有很多选择 - 这取决于它将如何使用。 - Reed Copsey
在我的实际代码中,我有两个属性(名称+包括开始的名称)。我现在有一个工作示例,但不幸的是,我的实际代码不起作用(逻辑完全相同):S。无论如何,我设置它的原因是项目本身负责正确显示它们。 - Sjors Miltenburg
请确保在更改任一属性(尤其是NameInclStart)时,PropertyChanged事件会触发。我建议添加第三个只读属性(DisplayName),并在设置Name或NameInclStart时调用NotifyChanged(...,“DisplayName”)。这将“修复”它。 - Reed Copsey

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