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

如何在WPF C#中使用数据绑定并解决数据源更新后控件未自动刷新的问题

嘿,我来帮你搞定这个WPF数据绑定的问题!你遇到的UI不更新问题,根源在于两个小细节没处理对,咱们一步步拆解解决:

问题出在哪?

你的代码里有两个核心原因导致DataGrid不更新:

  1. 直接赋值ItemsSource,没走数据绑定:你在Window_Loaded里直接把dg.ItemsSource设为personList1.People的引用——这是一次性的赋值操作。当你在Refresh里给personList1.People重新赋值时,DataGrid还握着原来那个List的引用,根本不知道有新集合出现。
  2. List不支持集合变更通知:就算你解决了第一个问题,List<T>本身没有实现INotifyCollectionChanged接口,以后如果你对集合做增删元素的操作,UI也不会自动同步这些变化。
怎么改?

我们需要做两个关键调整,顺便优化你的绑定逻辑:

1. 把List换成ObservableCollection

ObservableCollection<T>是WPF专门为数据绑定设计的集合类型,内置了集合变更通知机制,增删改元素都会自动通知UI更新。

2. 用数据绑定关联DataGrid和ViewModel属性

别再直接给dg.ItemsSource赋值了,通过绑定让DataGrid监听ListOfPerson的People属性变化。这样当People重新赋值时,UI会收到通知并自动切换数据源。

修改后的完整代码

首先更新实体类:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Person : INotifyPropertyChanged
{
    private string name;
    public Person() { }
    public Person(string value) => name = value;

    public string PersonName
    {
        get => name;
        set
        {
            name = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

public class ListOfPerson : INotifyPropertyChanged
{
    // 替换List为ObservableCollection
    private ObservableCollection<Person> people = new ObservableCollection<Person>();
    public ObservableCollection<Person> People
    {
        get => people;
        set
        {
            people = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

然后调整MainWindow的绑定逻辑:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ListOfPerson _personList1 = new ListOfPerson();
    private ListOfPerson _personList2 = new ListOfPerson();

    // 提供可绑定的属性,让UI能监听变化
    public ListOfPerson PersonList1
    {
        get => _personList1;
        set
        {
            _personList1 = value;
            OnPropertyChanged();
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        // 把窗口自身设为DataContext,方便绑定
        DataContext = this;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        PersonList1.People.Add(new Person { PersonName = "test1" });
        _personList2.People.Add(new Person { PersonName = "test2" });

        dg.AutoGenerateColumns = false;
        // 配置列的绑定路径
        var nameColumnBind = new Binding("PersonName") { Mode = BindingMode.TwoWay };
        dg.Columns.Add(new DataGridTextColumn { Header = "Name", Binding = nameColumnBind });

        // 用绑定设置ItemsSource,代替直接赋值
        var itemsSourceBind = new Binding("PersonList1.People");
        dg.SetBinding(DataGrid.ItemsSourceProperty, itemsSourceBind);
    }

    public void Refresh()
    {
        // 直接替换People集合,UI会自动更新
        PersonList1.People = _personList2.People;

        // 如果只是更新集合内容而非替换整个集合,也可以这么写:
        // PersonList1.People.Clear();
        // foreach(var person in _personList2.People)
        //     PersonList1.People.Add(person);
    }

    private void btn_Refresh_Click(object sender, RoutedEventArgs e) => Refresh();

    // 实现INotifyPropertyChanged,让PersonList1的变化能通知UI
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
额外小贴士
  • 按照MVVM最佳实践,建议把ListOfPerson这类ViewModel单独抽离出来,而不是让Window自己实现INotifyPropertyChanged——这样代码结构更清晰,也方便后续维护。
  • 如果以后只是修改集合里的单个Person的PersonName属性,因为你已经在Person类里实现了INotifyPropertyChanged,UI也会自动同步这些修改哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 09:44:07