DataGridViewでチェックボックスの列を一括で変更したいときに苦しんだメモです。
DataGridViewの値を取得したいとき
DataGridViewには、3つのValueが存在します。
- Value
- FormattedValue
- EdittedFormattedValue
Datagridviewは、実は表示用のDataGridViewが上にあり、その下に実際のDataGridViewが存在しています。つまり、自分で値を変更しても表示用のDataGridViewしか値が変わっていません。 上記のValueは、実際のDataGridViewの値を参照するため、Valueだと変更されていません。 FormattedValueが表示用のDataGridViewの値を参照するため、変更を感知するときはFormattedValueになります。 ちなみに、EdittedFormattedValueは、現在の書式指定済みの値を取得します。FormattedValueとの違いがまだ分かっていません。
DataGridViewのチェックボックスのColumn
DataGridViewは、Columnに型を設定できます。Columnにboolを設定すると、チェックボックスのColumnになります。上記の仕様の通り、変更すると表示用の値しか変わりません。他のセルを選択することによってはじめて、Valueが変更されます。これを解決するために、CurrentCellDirtyStateChanged()を使いました。
private void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
var dgv = (DataGridView)sender;
if (dgv.IsCurrentCellDirty)
{
dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
これで、チェックを入れた瞬間にValueも変更されます。
一括でチェックを入れたい
DataGridViewのセルを範囲選択して、チェックを入れられるようにしようと考えました。 DataGridViewのチェックボックスに設定したColumnに右クリックメニューを追加し、一括チェック操作を書きました。今回チェックを入れるColumnは、indexは1です。
foreach (DataGridViewCell a in dgv.SelectedCells)
{
if (a.ColumnIndex == 1)
{
a.Value = true;
}
}
セルの選択は複数Columnにわたることもできるので、回避のためColumnIndexを指定しています。表示ではすべてチェックが入ったのですが、実はValueが変更されていない場所が1か所ありました。*右クリックしたセルは、Valueが変更されていなかったのです。もっと調べると、一つずつ変更した場合はCurrentCellDirtyStateChangedが発火していますが、一括変更の場合は発火していませんでした。
解決法
チェックボックスの値を表示用が変更された瞬間にValueを変更するためには、EndEdit()を使います。これをすることで今回の問題は解決しました。
まとめ
DataGridViewのvalueの仕様から起こる挙動をチェックボックスの一括値変更から解説しました。DataGridViewの仕様を学んだので、次に生かしていこうと思います。