Bind Model to Winforms DataGridView, can not get old value when property changed

47 Views Asked by At

I have a Model (INotifyPropertyChanged) and bound to a DataGridView by BindingList, Once I edited a property of model instance, DataGridView's cell value updated before PropertyChanged raied. I have no idea why.

I am going to listen to BindingList's ListChanged (ItemChanged) event and get new value and old value of updating property, but DataGridView's cell value updated before raising this event, so that I can not get old value from DatGridView's cell.

Does anyone has some others solution to get both of new and old values when model's property changed? Great thanks!

Here is my code:

public partial class Form1 : Form
{
    public abstract class BindableBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        protected bool SetProperty<TValue>(ref TValue field, TValue newValue, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<TValue>.Default.Equals(field, newValue))
            {
                return false;
            }

            var dataGridView = Application.OpenForms.OfType<Form1>().First().dataGridView1;
            if (dataGridView.RowCount > 0)
                Debug.Print($"Before set value to field: {dataGridView.Rows[0].Cells[0].Value}");
            field = newValue;
            if (dataGridView.RowCount > 0)
                Debug.Print($"After set value to field But before raise PropertyChanged event: {dataGridView.Rows[0].Cells[0].Value}");
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            if (dataGridView.RowCount > 0)
                Debug.Print($"After raise PropertyChanged event: {dataGridView.Rows[0].Cells[0].Value}");
            return true;
        }
    }

    public class Model : BindableBase
    {
        private int age;

        public int Age { get => age; set => this.SetProperty(ref this.age, value); }
    }

    BindingList<Model> Models = new();

    public Form1()
    {
        this.InitializeComponent();
        this.dataGridView1.AutoGenerateColumns = true;
        this.dataGridView1.DataSource = this.Models;
        this.dataGridView1.Click += this.DataGridView1_Click;
    }

    private void DataGridView1_Click(object? sender, EventArgs e)
    {
        switch (this.dataGridView1.RowCount)
        {
            case 0:
                this.Models.Add(new Model() { Age = 10 });
                break;
            default:
                this.Models[0].Age = DateTime.Now.Microsecond;
                break;
        }
    }

Here is some logs, you can see that Cell value was updated when set value to field and before raising PropertyChanged event;

Before set value to field: 10
After set value to field But before raise PropertyChanged event: 478
After raise PropertyChanged event: 478

Before set value to field: 478
After set value to field But before raise PropertyChanged event: 744
After raise PropertyChanged event: 744
0

There are 0 best solutions below