WindowsフォームアプリのDataGridViewを用いてイベントの参加情報をまとめる表を作ってみました。
出欠情報列は、コンボボックスでできており、「欠席」と「出席」から選ぶことができます。集金状況列は、チェックボックスでできており、出欠情報列が「出席」の場合のみ活性化します。
ひとまず、DataGridViewCellChangedイベントを使ってデータグリッドビューの変更を検知するように作ってみます。
private void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
//編集中のセル
var cellEditing = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];
//編集中の列が「集金状況」の場合
if(cellEditing.OwningColumn.Name == "Join")
{
//変更するチェックボックスのセル
var cellCheck = dataGridView.Rows[e.RowIndex].Cells["Pay"] as DataGridViewCheckBoxCell;
//「出席の場合
if(cellEditing.Value.ToString() == "出席")
{
cellCheck.ReadOnly = false;
cellCheck.FlatStyle = FlatStyle.Standard;
cellCheck.Style.BackColor = Color.White;
}
//欠席の場合
if(cellEditing.Value.ToString() == "欠席")
{
cellCheck.ReadOnly = true;
cellCheck.FlatStyle = FlatStyle.Flat;
cellCheck.Style.BackColor = Color.Gray;
}
}
}
これで、欠席を選択した行のチェックボックスは非活性に変化するようになりました。
しかし、ここで問題点が。
CellValueChangedが発火するタイミングは、編集中のセルからフォーカスが外れたとき。すなわち、セルを編集した後、別のセルをクリックしないとイベントが発火しないのです。ユーザーからしたら不親切です。
データグリッドビューで値を変更した瞬間にCellValueChangedが発火するようにしたいので、CurrentCellDirtyStateChangedイベントを追加します。
CellValueChangedは「編集がコミットされたとき」、つまり、編集状態が解除された瞬間に発火しますが、CurrentCellDirtyStateChangedは、「編集が行われたとき」に発火します。
それなら、最初からCurrentCellDirtyStateChangedを使えばいいのではないかと思いますが、これだとイベント引数eで編集中のセルの情報が取得できません。
ということで、「編集された瞬間に内容を強制的にコミットし、CellValueChangedを発火させる」という方法をとるために以下のイベントハンドラを追加します。
private void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
var dataGridView = sender as DataGridView;
//コミットされていない内容がある
if (dataGridView.IsCurrentCellDirty)
{
dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
これで、セルの内容を変更した瞬間にCellValueChangedが発火するようになります。
「dirty」という単語は、「コミットされていない」という意味合いで使われるみたい
データグリッドビューにおけるセルの編集は、「内容変更」→「コミット」という流れで行われているという事を頭に入れておくと良いかと思います。
コメント