これは私のコードです:
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の位置を保存する方法は?
これが私が思いついた解決策です。行数が大きく変化しない限り、行を選択する必要はなく、更新後にスクロールバーを同じ領域に戻します。
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;
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
簡単な方法はブローコードです。
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];
DataGridView.CurrentRow
を使用して、getDataを起動する前に選択した行を保存し、グリッドがロードされた後にその行を選択できます。
この質問 DataGridViewで特定の行を選択する方法に答えました。
編集:WinFormsを使用していると思います
Edit2:そしてスクロールバーはどうですか?
このステートメントを使用して、最初に表示される行インデックスも保存できます
DataGridView.FirstDisplayedCell.RowIndex
@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;
別のフォーラムで、操作なしの解決策を見つけました。
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");
}
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;
これは、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;
これを大きなデータセットで機能させることができませんでした。私がした後、位置がリセットされました:
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;
};
私はこのようなことをしました。
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];
}
現在、ページが読み込まれるたびにデータを読み込んでいます。 Page.IsPostbackプロパティを使用して、ポストバックであるかどうかを確認することをお勧めします。
if(!Page.IsPostback)
{
dataGridView1.DataSource = bindingSource;
getData("SELECT * FROM cities");
}
これにより、DBの負荷が軽減され、選択に問題が発生しなくなります。