web-dev-qa-db-ja.com

DataGridViewのチェックボックス値変更イベントのトリガー

チェックボックス列があるグリッドビューがあり、セルの値が切り替わったらすぐに描画イベントをトリガーしたい。 ValueChaged、CellEndEdit、BeginEditを試し、選択モードとしてCellSelectを選択しました。最初の2つのイベントについては、現在のセルから出たり、前後に移動したりするなど、編集モードの終了時にイベントがトリガーされました。それは奇妙な動作です。

セル値が変更されるとすぐにグリッドビューでイベントをトリガーするものはありますか?

宜しくお願いします、

30
mustafabar

私の同僚は、CurrentCellDirtyStateChangedイベントをトラップすることを推奨しています。 http://msdn.Microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx を参照してください。

23
user120381

CellContentClickイベントを使用して、ユーザーがチェックボックスをクリックしたことを確認します。ユーザーが同じセルにいる場合でも、複数回起動します。 1つの問題は、値が更新されず、チェックされていない場合は常に「false」を返すことです。トリックは、Valueプロパティの代わりにセルの.EditedFormattedValueプロパティを使用することです。 EditedFormattedValueはチェックマークで追跡し、CellContentClickが発生したときにValueが保持することを望んでいます。

タイマーは必要ありません。派手なものは不要です。CellContentClickイベントを使用し、EditedFormattedValueを調べて、チェックボックスがどの状態になったのか、どの状態になったのかを確認します。 EditedFormattedValue = trueの場合、チェックボックスがチェックされています。

33
Christo

別の方法は、CellContentClickイベント(セルのValueプロパティで現在の値を提供しない)を処理し、grid.CommitEdit(DataGridViewDataErrorContexts.Commit)を呼び出して値を更新し、次にCellValueChangedを発生させて、実際の(つまり正しい)DataGridViewCheckBoxColumn値。

private void grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
   grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void grid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // do something with grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value
}

ターゲット.NETフレームワーク:2.0

20
Stuart

私は同じ問題を抱えていましたが、別の解決策を思いつきました:

ユーザーがチェックボックスをクリックしても値が変わらないように、列またはグリッド全体を「読み取り専用」にした場合。

幸いなことに、DataGridView.CellClickイベントは引き続き発生します。私の場合、cellClickイベントで次のことを行います。

if (jM_jobTasksDataGridView.Columns[e.ColumnIndex].CellType.Name == "DataGridViewCheckBoxCell")

ただし、チェックボックス列が複数ある場合は、列名を確認できます。

その後、データセットのすべての変更/保存を自分で行います。

4
James

小さなアップデート.... EditedFormattedValueの代わりにvalueの代わりにvalueを使用していることを確認してください。 valueが、最新のc#2010 expressで使用されているように、以下の方法でアクセスできます。

grdJobDetails.Rows[e.RowIndex].Cells[0].EditedFormattedValue

また、_CellValueChanged少数で提案または使用されるイベントは、場合によっては使用可能でなければなりませんが、セルのすべてのチェック/チェック解除を探している場合は、必ず_CellContentClickその他、通知ごとに毎回表示されるわけではない_CellValueChangedが起動されます。つまり、同じチェックボックスが何度もクリックされても、起動されません_CellValueChangedただし、たとえば交互にクリックすると、2つのchekboxがあり、次々にクリック_CellValueChangedイベントが発生しますが、通常、任意のセルがチェック/チェック解除されるたびに発生するイベントを探している場合は_CellValueChangedは発生しません。

4
user593029

最終的にこの方法で実装しました

  private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {

        if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
        {
            if (dataGridView1[e.ColumnIndex, e.RowIndex].GetContentBounds(e.RowIndex).Contains(e.Location))
            {
                cellEndEditTimer.Start();
            }
        }

    }

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    { /*place your code here*/}


    private void cellEndEditTimer_Tick(object sender, EventArgs e)
    {
        dataGridView1.EndEdit();
        cellEndEditTimer.Stop();
    }
4
mustafabar

CellContentClickイベントにフックしてみてください。 DataGridViewCellEventArgsにはColumnIndexとRowIndexがあるため、ChecboxCellが実際にクリックされたかどうかを確認できます。このイベントの良い点は、実際のチェックボックス自体がクリックされた場合にのみ起動することです。チェックボックスの周りのセルの白い領域をクリックしても、起動しません。これにより、このイベントが発生したときにチェックボックスの値が変更されたことをほぼ保証できます。その後、Invalidate()を呼び出して描画イベントをトリガーし、必要に応じてEndEdit()を呼び出して行の編集の終了をトリガーできます。

4
BFree

「EditingControlShowing」イベントは、チェックボックスの値を変更しても発生しません。チェックボックスセルの表示スタイルは変わらないためです。

私が使用した回避策は次のとおりです。 (CellContentClickイベントを使用しました)

    private void gGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if (string.Compare(gGridView1.CurrentCell.OwningColumn.Name, "CheckBoxColumn") == 0)
        {
            bool checkBoxStatus = Convert.ToBoolean(gGridView1.CurrentCell.EditedFormattedValue);
            //checkBoxStatus gives you whether checkbox cell value of selected row for the
            //"CheckBoxColumn" column value is checked or not. 
            if(checkBoxStatus)
            {
                //write your code
            }
            else
            {
               //write your code
            }
        }
    }

上記は私のために働いています。さらにサポートが必要な場合はお知らせください。

1
Yamanappa

簡単な解決策を見つけました。

セルをクリックした後、セルのフォーカスを変更するだけです。

private void DGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == "Here checkbox column id or name") {
        DGV.Item(e.ColumnIndex, e.RowIndex + 1).Selected = true;
        //Here your code

    }
}

(ckeckbox + 1)インデックスの列が存在するかどうかを確認することを忘れないでください。

1

CellClickおよびCellMouseClickの回答はすべて間違っています。これは、キーボードでセルの値を変更でき、イベントが発生しないためです。また、CurrentCellDirtyStateChangedは1回だけ起動します。つまり、同じボックスを複数回チェック/チェック解除すると、1つのイベントのみが取得されます。上記の回答のいくつかを組み合わせると、次の簡単な解決策が得られます。

private void dgvList_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvList.CurrentCell is DataGridViewCheckBoxCell)
        dgvList.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void dgvList_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // Now this will fire immediately when a check box cell is changed,
    // regardless of whether the user uses the mouse, keyboard, or touchscreen.
    //
    // Value property is up to date, you DO NOT need EditedFormattedValue here.
}
1
Eric Lindsey

DataGridビューでcheckedChangedイベントを使用する場合は、次のコードを使用します。

_private void grdBill_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    grdBill.CurrentCell =  grdBill.Rows[grdBill.CurrentRow.Index].Cells["gBillNumber"];
}

private void grdBill_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    calcBill();
}

private void calcBill()
{
    listBox1.Items.Clear();
    for (int i = 0; i < grdBill.Rows.Count - 1; i++)
    {
        if (Convert.ToBoolean(grdBill.Rows[i].Cells["gCheck"].Value) == true)
        {
            listBox1.Items.Add(grdBill.Rows[i].Cells["gBillNumber"].Value.ToString());
        }
    }
}
_

ここでは、グリッドのgrdBill = DataGridView1, gCheck = CheckBox in GridView(First Column), gBillNumber = TextBox(2列目)。

したがって、クリックごとにcheckchangedイベントを発生させたい場合は、最初にCellContentClickを実行します。ユーザーがテキストボックスをクリックすると発生し、次に現在のセルを次の列に移動します。したがって、CellEndEdit列が発生し、チェックボックスがチェックされているかどうか、およびリストボックスに「gBillNumber」を追加します(関数calcBill内)。

0
Jegan

最初の2つの答えを組み合わせることで、必要なものが得られました。 CurrentCellDirtyStateChangedイベントを使用して、EditedFormattedValueを調べました。

private void dgv_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
   DataGridView dgv = (DataGridView)sender;
   DataGridViewCell cell = dgv.CurrentCell;
   if (cell.RowIndex >= 0 && cell.ColumnIndex == 3) // My checkbox column
     {
        // If checkbox checked, copy value from col 1 to col 2
        if (dgv.Rows[cell.RowIndex].Cells[cell.ColumnIndex].EditedFormattedValue != null && dgv.Rows[cell.RowIndex].Cells[cell.ColumnIndex].EditedFormattedValue.Equals(true))
        {
           dgv.Rows[cell.RowIndex].Cells[1].Value = dgv.Rows[cell.RowIndex].Cells[2].Value;
        }
     }
}
0
Mike Pollitt

cellEndEditTimer.Start();

この行により、datagridviewはチェックボックスのリストを更新します

ありがとうございました。

0
Leandro

バインドされていないコントロール(つまり、コンテンツをプログラムで管理します)を操作し、EndEdit()を使用せずに、CurrentCellDirtyStateChangedを一度だけ呼び出してから、二度と呼び出しません。しかし、EndEdit()でCurrentCellDirtyStateChangedが2回呼び出されることがわかりました(2番目はおそらくEndEdit()が原因ですが、チェックしませんでした)。

    bool myGridView_DoCheck = false;
    private void myGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (!myGridView_DoCheck)
        {
            myGridView_DoCheck = true;
            myGridView.EndEdit();
            // do something here
        }
        else
            myGridView_DoCheck = false;
    }