web-dev-qa-db-ja.com

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");
    }

button1クリックでデータを再読み込みすると、セルの選択が最初の列にジャンプし、スクロールバーがリセットされます。 DataGridViewの位置を保存する方法は?

16
bobik

これが私が思いついた解決策です。行数が大きく変化しない限り、行を選択する必要はなく、更新後にスクロールバーを同じ領域に戻します。

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;
35
ovinophile
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
4
Dave Lucre

簡単な方法はブローコードです。

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];
3
The_Mind_Hunter

DataGridView.CurrentRowを使用して、getDataを起動する前に選択した行を保存し、グリッドがロードされた後にその行を選択できます。

この質問 DataGridViewで特定の行を選択する方法に答えました。


編集:WinFormsを使用していると思います

Edit2:そしてスクロールバーはどうですか?

このステートメントを使用して、最初に表示される行インデックスも保存できます

DataGridView.FirstDisplayedCell.RowIndex
3
Javier

@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;
2
Mako-Wish

別のフォーラムで、操作なしの解決策を見つけました。

    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");
    }
1
bobik

SelectionChangedDataGridViewイベントを使用して、選択した行を追跡できます。問題は、データソースを再バインドするときの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;
0
clamchoda

これは、DataGridViewコントロールのDataSourceプロパティをリセットまたは再影響するためです。

必要な処理を実行するには、DataGridViewのDataSourceプロパティをリセットする前に、CurrentItemインデックスをローカル変数に保存する必要があります。ただし、そうすることは、同じかそれ以上の量のデータがあることを知っていることを意味します。そうしないと、DataGridViewに実際に含まれているデータの量よりも多いインデックスに移動しようとするIndexOutOfRangeExceptionが発生します。

したがって、行またはセルのインデックスを保存する場合は、BindingSourceがそのような機能を提供しないため、DataGridViewコントロールプロパティを介して保存する必要があります。

DataGridViewでは、選択した行と現在の行(行ヘッダーの矢印で示されている)が同じ行ではない場合があります。さらに、DataGridViewで複数の行を選択することもできますが、現在の行は1行のみにすることができます。 DataGridViewのSelectionModeプロパティがFullRowSelectに設定されている場合、現在の行が常に選択されます。 DataGridViewコントロールの現在の行を変更する場合は、CurrentCellプロパティを設定できます。

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

選択した行を変更するだけの場合は、trueにする行のSelectedプロパティを設定できます。

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

これを大きなデータセットで機能させることができませんでした。私がした後、位置がリセットされました:

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;
        };
0
Bassebus

私はこのようなことをしました。

  1. FirstDisplayedCellとCurrentCellを選択して保存
  2. 更新
  3. DataGridViewの前の行を設定し、前に選択した行を設定します

    //変数を宣言しますintrowIndex = 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];
    }
    
0
levinjay

現在、ページが読み込まれるたびにデータを読み込んでいます。 Page.IsPostbackプロパティを使用して、ポストバックであるかどうかを確認することをお勧めします。

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

これにより、DBの負荷が軽減され、選択に問題が発生しなくなります。

0
Lucas