Como faço para impedir que um DataGridView seja automático quando a fonte de dados muda?

StackOverflow https://stackoverflow.com/questions/1521396

  •  19-09-2019
  •  | 
  •  

Pergunta

Eu tentei isso (http://brainof-deve.blogspot.com/2007/08/turning-of-auto-scrolling-in-bound.html) no evento "RowChanged" no DataTable, que é a fonte de dados para o DataGridView, mas sem sucesso.

Basicamente, eu tenho um DataGridView com um BindingSource, pois é o DataSource. O DataSource da BindingSource é uma View do DataView que contém um DataTable. Sempre que os dados em uma das linhas mudam, o DataGridView rola de volta para o topo. Existe uma correção simples para isso?

Foi útil?

Solução

Parece que eu encontrei: http://seewinapp.blogspot.com/2005/09/is-your-autoscroll-too-auto.html

Eu substituí o evento RowChanged no DataTable, armazenei o primeiro displayedScrollingRowIndex, invocei um método delegado com esse índice como argumento e depois redefinindo o primeiro divulgado que o RollingRowIndex para esse argumento dentro do método delegado. Acontece que a rolagem automática não ocorre até que todos os eventos tenham sido disparados, por isso é inútil tentar invadi-lo dentro de um evento. O delegado funciona porque é invocado após os eventos.

Outras dicas

Aqui é o código testado que restaura o RowIndex após a alteração do DataSource. Isso também restaura a ordem de classificação e a última posição da célula. Idioma: C# 7.0. Este é o código que escrevi pessoalmente, com alguma ajuda de pesquisas na web.

    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);
        }
    } 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top