How do I prevent a DataGridView from autoscrolling when the datasource changes?

北战南征 提交于 2019-12-22 10:44:27

问题


I tried this (http://brainof-dave.blogspot.com/2007/08/turning-off-auto-scrolling-in-bound.html) in the "RowChanged" event on the DataTable that is the data source for the DataGridView, but to no avail.

Basically, I have a DataGridView with a BindingSource as it's DataSource. The BindingSource's DataSource is a DataView that contains a DataTable. Every time data in one of the rows changes, the DataGridView scrolls back to the top. Is there a simple fix for this?


回答1:


Looks like I found it: http://seewinapp.blogspot.com/2005/09/is-your-autoscroll-too-auto.html

I overrode the RowChanged event on the DataTable, stored the FirstDisplayedScrollingRowIndex, invoked a delegate method with that index as the argument, and then reset the FirstDisplayedScrollingRowIndex to that argument inside the delegate method. It turns out that auto-scroll doesn't occur until after all events have been fired, so it's useless to try to hack it inside an event. The delegate works because it is invoked after the events.




回答2:


Here is tested code that restores the RowIndex after changing the datasource. This also restores the sort order and last cell position. Language: C# 7.0. This is code I wrote personally, with some help from web searches.

    private void UpdateDataSource()
    {
        SuspendLayout();

        //Save last position and sort order
        DataGridView g = DataGridView1;
        Int32 idxFirstDisplayedScrollingRow = g.FirstDisplayedScrollingRowIndex;
        SortOrder dgvLastSortDirection = g.SortOrder;
        Int32 lastSortColumnPos = g.SortedColumn?.Index ?? -1;
        Int32 dgvLastCellRow = g.CurrentCell?.RowIndex ?? -1;
        Int32 dgvLastCellColumn = g.CurrentCell?.ColumnIndex ?? -1;

        //Set new datasource
        g.DataSource = myNewDataTableSource;                                                                     

        //Restore sort order, scroll row, and active cell
        g.InvokeIfRequired( o =>
        {
            if(lastSortColumnPos > -1)
            {
                DataGridViewColumn newColumn = o.Columns[lastSortColumnPos];
                switch(dgvLastSortDirection)
                {
                    case SortOrder.Ascending:
                        o.Sort(newColumn, ListSortDirection.Ascending);
                        break;
                    case SortOrder.Descending:
                        o.Sort(newColumn, ListSortDirection.Descending);
                        break;
                    case SortOrder.None:
                        //No sort
                        break;
                }
            }

            if(idxFirstDisplayedScrollingRow >= 0)
                o.FirstDisplayedScrollingRowIndex = idxFirstDisplayedScrollingRow;

            if(dgvLastCellRow>-1 && dgvLastCellColumn>-1)
                o.CurrentCell = g[dgvLastCellColumn, dgvLastCellRow];
        } );

        ResumeLayout();
    }

    public static void InvokeIfRequired<T>(this T obj, InvokeIfRequiredDelegate<T> action) where T : ISynchronizeInvoke
    {
        if (obj.InvokeRequired)
        {
            obj.Invoke(action, new Object[] { obj });
        }
        else
        {
            action(obj);
        }
    } 


来源:https://stackoverflow.com/questions/1521396/how-do-i-prevent-a-datagridview-from-autoscrolling-when-the-datasource-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!