Как сохранить позицию после перезагрузки DataGridView

это мой код:

        private void getData(string selectCommand)
    {
        string connectionString = @"Server=localhost;User=SYSDBA;Password=masterkey;Database=C:\data\test.fdb";

        dataAdapter = new FbDataAdapter(selectCommand, connectionString);
        DataTable data = new DataTable();
        dataAdapter.Fill(data);
        bindingSource.DataSource = data;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        getData(dataAdapter.SelectCommand.CommandText);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.DataSource = bindingSource;
        getData("SELECT * FROM cities");
    }

после перезагрузки данных на кнопке 1 щелчок, переходы в ячейке для первого столбца и полосы прокрутки reset. Как сохранить положение DataGridView?

Ответ 1

Вот решение, которое я придумал. Не требует выбора строки и помещает полосу прокрутки обратно в ту же область после обновления, при условии, что количество строк не сильно меняется.

int saveRow = 0;
if (dataGridView1.Rows.Count > 0 && dataGridView1.FirstDisplayedCell != null)
    saveRow = dataGridView1.FirstDisplayedCell.RowIndex;

dataGridView1.DataSource = dataTable1;

if (saveRow != 0 && saveRow < dataGridView1.Rows.Count)
    dataGridView1.FirstDisplayedScrollingRowIndex = saveRow;

Ответ 2

int FirstDisplayedScrollingRowIndex = this.dgvItems.FirstDisplayedScrollingRowIndex; //Save Current Scroll Index
int SelectedRowIndex = 0;
if (this.dgvItems.SelectedRows.Count > 0) SelectedRowIndex = this.dgvItems.SelectedRows[0].Index; //Save Current Selected Row Index

//REFRESH DataGridView HERE

if ((FirstDisplayedScrollingRowIndex >=0) && ((this.dgvItems.Rows.Count -1) >= FirstDisplayedScrollingRowIndex)) this.dgvItems.FirstDisplayedScrollingRowIndex = FirstDisplayedScrollingRowIndex; //Restore Scroll Index
if ((this.dgvItems.Rows.Count -1) >= SelectedRowIndex) this.dgvItems.Rows[SelectedRowIndex].Selected = true; //Restore Selected Row

Ответ 3

Вы можете сохранить выбранную строку перед запуском getData с помощью DataGridView.CurrentRow и выбрать эту строку после загрузки Grid.

В этот вопрос Я ответил, как выбрать определенную строку в DataGridView.


Изменить: Я предположил, что вы используете WinForms

Edit2: А как насчет полос прокрутки?

Вы также можете сохранить первый индекс видимой строки с помощью этого оператора

DataGridView.FirstDisplayedCell.RowIndex

Ответ 4

Простым способом является код Blow:

int CurrentRowIndex = (hSuperGrid1.CurrentRow.Index);

////after Fill The DataGridView

hSuperGrid1.ClearSelection();
hSuperGrid1.CurrentRow.Selected = false;

hSuperGrid1.Rows[CurrentRowIndex].Selected = true;

hSuperGrid1.CurrentCell = hSuperGrid1[0, CurrentRowIndex];

Ответ 5

Ответ на

@ovinophile помог, конечно, но он не касался горизонтальной прокрутки DataGridView для меня. Подвижная реакция на @ovinophile отвечает, это хорошо работает для поддержания горизонтальной и вертикальной позиции прокрутки:

// Remember the vertical scroll position of the DataGridView
int saveVScroll = 0;
if (DataGridView1.Rows.Count > 0)
    saveVScroll = DataGridView1.FirstDisplayedCell.RowIndex;

// Remember the horizontal scroll position of the DataGridView
int saveHScroll = 0;
if (DataGridView1.HorizontalScrollingOffset > 0)
    saveHScroll = DataGridView1.HorizontalScrollingOffset;

// Refresh the DataGridView
DataGridView1.DataSource = ds.Tables(0);

// Go back to the saved vertical scroll position if available
if (saveVScroll != 0 && saveVScroll < DataGridView1.Rows.Count)
    DataGridView1.FirstDisplayedScrollingRowIndex = saveVScroll;

// Go back to the saved horizontal scroll position if available
if (saveHScroll != 0)
    DataGridView1.HorizontalScrollingOffset = saveHScroll;

Ответ 6

На другом форуме я нашел решение без каких-либо манипуляций:

    private void getData(string selectCommand)
    {
        string connectionString = @"Server=localhost;User=SYSDBA;Password=masterkey;Database=C:\data\test.fdb";

        dataAdapter = new FbDataAdapter(selectCommand, connectionString);
        data = new DataTable();
        dataAdapter.Fill(data);
        bindingSource.DataSource = data;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        dataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
        dataAdapter.Fill(data);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.DataSource = bindingSource;
        getData("SELECT * FROM cities");
    }

Ответ 7

В настоящее время вы загружаете данные каждый раз, когда страница загружается. Я бы предложил использовать свойство Page.IsPostback, чтобы проверить и проверить, является ли это обратной передачей или нет.

if(!Page.IsPostback)
{
    dataGridView1.DataSource = bindingSource;  
    getData("SELECT * FROM cities");
}

Это уменьшит нагрузку на вашу БД и перестанет вызывать проблемы с вашими выборами.

Ответ 8

Это происходит потому, что вы сбросили или повторно применили свойство DataSource вашего элемента управления DataGridView.

Чтобы выполнить то, что вам нужно, вам нужно сохранить индекс CurrentItem в локальную переменную перед сбросом свойства DataSource вашего DataGridView. Однако это означает, что вы знаете, что у вас будет одинаковое или большее количество данных, иначе вы получите исключение IndexOutOfRangeException, пытаясь перейти к большему индексу, чем объем данных, фактически содержащийся в вашем DataGridView.

Итак, если вы хотите сохранить индекс своей строки или ячейки, вам нужно выполнить ее через свойства управления DataGridView, так как ваш BindingSource не будет предоставлять такую ​​функцию.

В DataGridView выбранная строка и текущей строки (обозначенной стрелка в заголовке строки) не может быть той же строки. Кроме того, мы могли бы выберите несколько строк в DataGridView но текущая строка может быть только одной ряд. Когда свойство SelectionMode для DataGridView установлено значение FullRowSelect, текущая строка будет всегда выбран. Если вы хотите изменить текущую строку в DataGridView, вы можете установить Свойство CurrentCell

dataGridView1.CurrentCell = dataGridView1.Rows[1].Cells[0]; 

Если вы хотите просто изменить выбранную строку, вы можете установить свойство Selected строки, которую вы хотите присвоить true.

dataGridView1.CurrentRow.Selected = false; 
dataGridView1.Rows[1].Selected = true; 

Ответ 9

Я сделал что-то вроде этого.

  1. Сохранить выбранные FirstDisplayedCell и CurrentCell
  2. Обновить
  3. Установить dataGridView предыдущую строку и установить предыдущую выбранную строку

    //Объявляем переменные   int rowIndex = 0;   int saveRow = 0;

    if(dataGridView1.SelectedRows.Count > 0)
    {
        rowIndex = dataGridView1.CurrentCell.RowIndex;
        saveRow = dataGridView1.FirstDisplayedCell.RowIndex;
    }
    
    //REFRESH CODE HERE
    
    if(dataGridView1.SelectedRows.Count > 0)
    {
        dataGridView1.FirstDisplayedScrollingRowIndex = saveRow;
        dataGridView1.CurrentCell = dataGridView1.Rows[rowIndex].Cells[0];
    }
    

Ответ 10

Мы можем использовать событие SelectionChanged DataGridView для отслеживания выбранной строки. Проблема в том, что при повторном связывании источника данных CurrentRow.Index сбрасывается в ноль.

Мы можем справиться с этим, отсоединившись от события SelectionChanged перед привязкой нашего источника данных и повторно подключив его к событию после привязки нашего источника данных.

// Detach Event
dataGridView1.SelectionChanged -= dataGridView1_SelectionChanged;
// Bind Data
bindingSource.DataSource = data; // or dataGridView1.DataSource = data;
// Set Selected Row
dataGridView1.Rows[LastSelectedRowIndex].Selected = true;
// Re-attach Event
dataGridView1.SelectionChanged += dataGridView1_SelectionChanged;

Событие для отслеживания выбранного индекса простое.

int LastSelectedRowIndex = 0;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
     LastSelectedRowIndex = dataGridView1.CurrentRow.Index;  
}

Это чтобы дать вам представление о концепции.

Сохранить выбор с помощью уникального значения ключа

Обычно, когда мы привязываем информацию к источнику данных, это происходит потому, что информация изменилась. Если размер набора данных изменился, это означает, что ваши индексы строк также изменятся.

Вот почему мы не должны полагаться на LastSelectedRowIndex для поддержания выбранной строки. Вместо этого мы должны использовать уникальный ключ в источнике данных.

Наше SelectionChanged событие становится следующим.

// KeyIndex is the Unique Key column within your dataset.
int KeyIndex = 2;
string LastSelectedKey = string.Empty;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
     LastSelectedKey = dataGridView1.CurrentRow.Cells[KeyIndex].Value.ToString();
}

И вместо установки выбранной строки DataGridView по индексу мы можем установить ее по значению ключа.

// Set Selected Row
// If we need to scroll the selected row into view
// this would be a good place to set FirstDisplayedScrollingRowIndex
foreach (DataGridViewRow row in dataGridView1.Rows)
     if (row.Cells[KeyIndex].Value.ToString() == LastSelectedKey)
          row.Selected = true;

Ответ 11

Я не мог заставить это работать с большими наборами данных. Позиция была сброшена после того, как я это сделал:

saveRow = dataGridView1.FirstDisplayedScrollingRowIndex;
*** refresh data ***
dataGridView1.FirstDisplayedScrollingRowIndex = saveRow;
*** Now we still got a reset ***

Возможно, потому что набор данных не был загружен до того, как я сбросил saveRow.

Решение, которое сработало для меня, состояло в том, чтобы сбросить позицию внутри события DataBindingComplete, например, так:

        dataGridView1.DataBindingComplete += (o, args) =>
        {
            if(dataGridView1.RowCount > 0 && saveRow < dataGridView1.RowCount && saveRow > 0)
                dataGridView1.FirstDisplayedScrollingRowIndex = saveRow;
        };