You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中ListBox使用DisplayMemberPath时绑定属性及列表更新问题

WPF ListBox 绑定集合后无法更新的解决方法

问题核心

你的代码无法更新ListBox的原因有两个:

  1. 自定义的People集合未实现INotifyCollectionChanged接口——WPF的ItemsSource依赖这个接口感知集合的元素添加/删除/移动操作,才能自动更新UI。
  2. 错误调用OnPropertyChanged("Name")——Name是Person类的属性,而ListBox绑定的是整个container集合,集合元素变化和单个Person的Name属性无关。

方案一:直接使用ObservableCollection(推荐)

ObservableCollection<T>是WPF内置的可观察集合,已经实现了INotifyCollectionChanged和INotifyPropertyChanged,无需手动处理通知逻辑。

修改后代码

MainWindow.xaml.cs

using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows;

namespace GUITest2;

public partial class MainWindow : Window {
    // 用ObservableCollection替代自定义People类
    public ObservableCollection<Person> Container { get; set; } = new();

    public MainWindow() {
        InitializeComponent();
        // 初始化默认数据
        Container.Add(new Person { Name = "Bob" });
        Container.Add(new Person { Name = "Jeff" });
        DataContext = this;
    }

    [RelayCommand]
    public void Button() {
        Container.Add(new Person { Name = "Harry" });
        // ObservableCollection会自动触发集合变化通知,无需手动调用OnPropertyChanged
    }
}

public class Person {
    public string Name { get; internal set; } = "";
}

MainWindow.xaml(修正绑定路径大小写)

<ListBox ItemsSource="{Binding Container}" DisplayMemberPath="Name" Height="100"/>

方案二:自定义集合实现INotifyCollectionChanged(保留People类)

如果需要保留自定义People类的结构,可通过封装ObservableCollection来实现集合变化通知:

using System.Collections.ObjectModel;
using System.Collections.Specialized;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections;

namespace GUITest2;

public class People : ObservableObject, IEnumerable<People.Person>, INotifyCollectionChanged {
    private readonly ObservableCollection<Person> _dataList = new();

    public People() {
        _dataList.Add(new Person { Name = "Bob" });
        _dataList.Add(new Person { Name = "Jeff" });
        // 转发ObservableCollection的集合变化事件
        _dataList.CollectionChanged += (s, e) => CollectionChanged?.Invoke(this, e);
    }

    public void Add(string name) {
        _dataList.Add(new Person { Name = name });
    }

    public IEnumerator<Person> GetEnumerator() => _dataList.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => _dataList.GetEnumerator();

    // 实现INotifyCollectionChanged接口的事件
    public event NotifyCollectionChangedEventHandler? CollectionChanged;
}

MainWindow的原有代码无需修改,点击按钮添加元素时ListBox会自动更新。


额外说明

  • ListBox监听的是集合的CollectionChanged事件,而非单个属性的PropertyChanged事件,因此不需要传递任何PropertyName。
  • 如果后续需要替换整个container集合对象(比如从new People()换成另一个实例),需将container改为支持属性变化通知的属性,比如使用CommunityToolkit.Mvvm的[ObservableProperty]:
    [ObservableProperty]
    private People _container = new();
    
    此时XAML绑定路径需改为Container(自动生成的属性名),替换集合时会自动触发通知。

内容的提问来源于stack exchange,提问作者systemloc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 01:15:41