3

[C#、Visual Studio 2008、Windows 7 64]

クラスにDataGridViewがあります。このデータグリッドビューはDataGridViewCheckBoxColumnを使用するため、各セルにチェックボックスが含まれます。

これは、行の1つのスクリーンショットです。

DataGridViewチェックボックス

ユーザーがセルを選択したかどうかを検出できるようにしたい(セル内のどこかで、チェックボックスの上ではない)。また、ユーザーがチェックボックスを選択したことを検出したいと思います。これを行うには、コードで両方のイベントのコールバックを設定する必要があります。

this.CellClick += cellClick; // callback when the user selects a cell
this.CellContentClick += cellContentClick; // callback when the user selects a checkbox

コールバックメソッドは次のとおりです。

    private void cellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        toggleCellCheck(e.RowIndex, e.ColumnIndex);
    }

    private void cellClick(object sender, DataGridViewCellEventArgs e)
    {
        toggleCellCheck(e.RowIndex, e.ColumnIndex);
    }

    private void toggleCellCheck(int row, int column)
    {
        bool isChecked = (bool)this[column, row].EditedFormattedValue;
        this.Rows[row].Cells[column].Value = !isChecked;
    }

注:ご覧のとおり、 toggleCellCheckメソッドはチェックボックスの値を取得して切り替え、チェック済み->チェックなしまたはチェックなし->チェック済みです。)

ユーザーがチェックボックス以外のセル内の任意の場所をクリックすると、cellClickという1つのコールバックのみが発生します。その後、toggleCellCheckメソッドが呼び出され、チェックボックスの状態が反転します。

これは私が望む正確な振る舞いです。

私が抱えている問題は、ユーザーがチェックボックスを直接クリックすると、両方のイベントがcellClickcellContentClickの順に発生することです。

両方のコールバックが実行されると、チェックボックスオンになっている状態が最初のコールバックの後に切り替えられ、2番目のコールバックの後に再び切り替えられます。もちろん、最終的な結果は、チェックボックスがオンになっているステータスは変更されないということです。

両方のコールバックが発生しないようにDataGridViewクラスを構成する方法はありますか?または、これが2番目のコールバックであることを( cellContentClickメソッド内で)検出する方法はありますか、またはコールバックがチェックボックスをクリックして生成され、toggleCellCheckを呼び出さずに終了する方法はありますか?

私は次のようなことを考えていました:

private void cellContentClick(object sender, DataGridViewCellEventArgs e)
{
    // if sender/sender child/etc. is of type checkbox then return because
    // _cellClick_ has already been called to change the checkbox checked property
    // something like the following:
    //
    // if (typeof(sender) == CheckBox) return;
    // else toggleCellCheck(e.RowIndex, e.ColumnIndex);
}

ありがとう!

1月

4

2 に答える 2

3

セルコンテンツクリックハンドラーは必要ありません。チェックボックスが選択されている場合、セルクリックが呼び出されます。

最終的な目標は、クリックされたセルのコンテンツと、クリックされた実際のチェックボックス1にグリッドが応答するようにすることです。

これを行うには、次のようなセルクリックイベントにアタッチするだけです。

void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    if (dataGridView1.Columns[e.ColumnIndex].Name == "checkboxcolumn")
    {
        Console.WriteLine("Click");
        bool isChecked = (bool)dataGridView1[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
        dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = !isChecked;
        dataGridView1.EndEdit();
    }
}

1.この種のUIの変更はお勧めしません。DataGridViewなどのコントロールのデフォルトの動作は広く普及しており、十分にテストされています。それらを変更することは通常悪い考えです。

于 2012-08-20T14:42:10.880 に答える
0
private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    DataGridViewCheckBoxCell dgvcell = (DataGridViewCheckBoxCell)dataGridView2[e.ColumnIndex, e.RowIndex]; 
    if ( ( Convert.ToBoolean(dataGridView2[e.ColumnIndex, e.RowIndex].Value ) == true ) )
             { 
                 dgvcell.Value = CheckState.Unchecked;
                 lst_box2.Items.Add(dataGridView2.Rows[e.RowIndex].Cells["ItemName"].Value.ToString());
                 lst_box1.Items.Remove(dataGridView2.Rows[e.RowIndex].Cells["ItemName"].Value.ToString());
            } 
            else 
            { 
                lst_box1.Items.Add(dataGridView2.Rows[e.RowIndex].Cells["ItemName"].Value.ToString());
                lst_box2.Items.Remove(dataGridView2.Rows[e.RowIndex].Cells["ItemName"].Value.ToString());
                dgvcell.Value = CheckState.Checked;
            } 

}
于 2012-12-31T09:14:52.270 に答える