views:

279

answers:

2

Here's my problem : I have a DataGridView bound to a BindingList of custom objects. A background thread is constantly updating a value of these objects. The udpates are showing correctly, and everything is fine except for one thing - If you try to edit a different field while the background-updated field is being updated, it loses the entered value. Here is a code sample that demonstrates this behavior: (for new form, drop a new DataGridView on:)

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private BindingList<foo> flist;
        private Thread thrd;
        private BindingSource b;
        public Form1()
        {
            InitializeComponent();
            flist = new  BindingList<foo>
                    {
                        new foo(){a =1,b = 1, c=1}, 
                        new foo(){a =1,b = 1, c=1}, 
                        new foo(){a =1,b = 1, c=1}, 
                        new foo(){a =1,b = 1, c=1}
                    };
            b = new BindingSource();
            b.DataSource = flist;
            dataGridView1.DataSource = b;
            thrd = new Thread(new ThreadStart(updPRoc));
            thrd.Start();

        }

        private void upd()
        {
            flist.ToList().ForEach(f=>f.c++);
        }  

        private void updPRoc()
        {
            while (true)
            {
                this.BeginInvoke(new MethodInvoker(upd));
                Thread.Sleep(1000);
            }
        }
    }


    public class foo:INotifyPropertyChanged
    {
       private int _c;
       public  int a { get; set; }
       public int b { get; set; }
       public int c 
       { 
           get {return _c;}
           set
           {
               _c = value;
               if (PropertyChanged!= null)
                   PropertyChanged(this,new PropertyChangedEventArgs("c"));
           }
       }

       #region INotifyPropertyChanged Members

       public event PropertyChangedEventHandler PropertyChanged;

       #endregion
    }
}

So, you edit column a or b, you will see that the column c update causes you to lose your entry.

Any thoughts appreciated.

A: 

Hi yoni.s.

I've played a bit with your code. It seems that what is happening is that as soon as you add a new row, a new "foo" object is automatically added to the BindingList via the 'DataGridView's add-row functionality. Since it's as valid as an object in the collection, its 'c' parameter will be incremented by the thread function you've implemented and your input changes will be lost, since the PropertyChangedEvent firing will cause the 'DataGridView' to refresh.

What I suggest is to have a different view, or form, where you enter the information of the new object. Then at OK, add the new foo object to the list. This defeats the purpose of adding the rows straight from the DataGridView I know that and argue with me if you like, but you could have all your validation somewhere else. Would you want to code for all your validation and correctedness-checks inside UI code? Would you want a user to deal with "You needed a number and not text there!" messages while the rest of the DataGridView is updating? Could be a bit frustrating.

Also, if the data is to be constantly changing, there is little point making it editable from the gridview. You want a connected-approach paradigm to the datasource where some of it is constantly changing.. you might want to reconsider how you're showing this information and maybe have the user see the data and edit it a different way.

My 5 cents anyway.

Good luck yoni, it was fun to see the numbers go crazy and I understand your problem.

Leo Bruzzaniti

lb
Perhaps my question was not clear enough - the issue is not occurring on adding a new row, but when you are in the middle of changing column a or b of an existing row. Also, column C is not editable (in my app). IN light of the lack of other answers, I'm going to assume that "this behavior is by design", and that a PropertyChanged event will always cause current data entries to be lost. The good news is that the workaround described in my prior comment does work.
Sorry for not being able to answer correctly - I think that editing a newly added row and editing a current one in this context is the same thing.. as when adding you are put rightaway in editing mode and still suffer from the problem. Thanks for the feedback!
lb
A: 

Before saving assign currentCell property of the datagridview to nothing so that it loses focus from the cell being edited

Amit Karmakar