Link to home
Start Free TrialLog in
Avatar of openshac
openshac

asked on

Prevent DataGridView from resorting when its DataSource is updated

I have a DataGridView which is bound to an underlying DataTable, which I am able to sort by clicking on the column headers.

However every minute I need to update the DataTable (values in the columns change, but no rows are added/deleted).

When I rebind the DataTable to the DataGridView.DataSource the grid get's unsorted.
(I've tried just updating the DataTable and tried using a BindingSource but the problem seems to be the same)

In the end the only way I was able to do it was to make a note of the last column to be sorted and the direction and then reapply this once the data has been refreshed.

Is there a cleaner way to preserve the sort order when the underlying data is refreshed?
Avatar of lof
lof
Flag of United Kingdom of Great Britain and Northern Ireland image

first you need to accept changes on data table

dataTable1.AcceptChanges();

and then you need to refresh the datagrid

dataGridView1.Refresh();
Avatar of openshac
openshac

ASKER

Hi lof,
Thanks for replying, I have tried what you suggested but the DataGridView doesn't seem to update when I call Refresh()
I tried resetting the DataSource with:
    dataGridView1.DataSource = _dt;
but that just unsorts the DataGridView.
Is there something I'm doing wrong?

        DataTable _dt = new DataTable();
        int _counter = 0;

        private void GridSort_Load(object sender, EventArgs e)
        {
            _dt = GetData();
            dataGridView1.DataSource = _dt;

            dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Descending);
            
            _dt = GetData();
            _dt.AcceptChanges();
            dataGridView1.Refresh();
        }

        private DataTable GetData()
        {            
            DataTable dt = new DataTable();
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("Number", typeof(Int32));

            for (int i = 0; i < 100; i++)
            {
                dt.Rows.Add(new string[] { "Name" + i.ToString() + " " + _counter.ToString(), i.ToString() });
            }

            _counter++;
            return dt;
        }

Open in new window

The problem occures when you set the DataSource property multiple times. Try this example. I've added one button to add rows one by one after initial load
the code is here
public partial class Form1 : Form
    {
        DataTable _dt;
        int _counter = 0;
        DataView _dv;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _dt = new DataTable();
    

            _dt = GetData();
            _dt.AcceptChanges();
            dataGridView1.DataSource = _dt;
            dataGridView1.Refresh();
            dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Descending);
        }


        private void button1_Click(object sender, EventArgs e)
        {
            object[] objs = { "X", "0" };
            _dt.Rows.Add(objs);
            _dt.AcceptChanges();
            dataGridView1.Refresh();

        }

        void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        private void GridSort_Load(object sender, EventArgs e)
        {
            
        }

        private DataTable GetData()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("Number", typeof(Int32));

            for (int i = 0; i < 100; i++)
            {
                dt.Rows.Add(new string[] { "Name" + i.ToString() + " " + _counter.ToString(), i.ToString() });
            }

            _counter++;
            return dt;
        }
    }

Open in new window

I did not get your point why you make re-binding? the binding source will fix this problem because you can assigin a Sort expression on it and it will automatically display any changes in the DataSource (your data table) and will sort records according to your sorting expression.
Rebinding was causing problems that is why I said you need to set DataSource only once and than it works.
try to make BindingSource for example call it myBindingSource and assign your datasource of it.

write:
myBindingSource.Sort = " mycolumn1, mycolumn2, mycolumn2 ";
at your FormLoad event


lof,
I get my updated DataTable from the database, I am not adding/removing rows.  However vritually all the data in the table is changing slightly (they are actually time dependant prices).
I don't want to have to modify each row individually when I get a new dataset.
ASKER CERTIFIED SOLUTION
Avatar of openshac
openshac

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The reason of the problem was explained and solution - not rebinding or recreating the DataTable object - provided.

By duing Merge you update the table similarily to adding rows manualy in terms that the DataTable object is not recreated.
lof,

You solution involved adding new rows, in the original question it states:
"but no rows are added/deleted"

So the code you kindly provided did not work for the original question as stated.

Thanks any for taking time to help