C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

DataGridViewCheckBoxCellについて /MTK (18/04/13(Fri) 14:19) #87121
Re[1]: DataGridViewCheckBoxCellについて /Hongliang (18/04/13(Fri) 14:52) #87124
│└ Re[2]: DataGridViewCheckBoxCellについて /MTK (18/04/13(Fri) 15:48) #87125
│  └ Re[3]: DataGridViewCheckBoxCellについて /PANG2 (18/04/13(Fri) 16:06) #87126
│    └ Re[4]: DataGridViewCheckBoxCellについて /MTK (18/04/13(Fri) 17:10) #87129
│      └ Re[5]: DataGridViewCheckBoxCellについて /PANG2 (18/04/13(Fri) 17:32) #87130
│        └ Re[6]: DataGridViewCheckBoxCellについて /MTK (18/04/13(Fri) 18:10) #87131
│          └ Re[7]: DataGridViewCheckBoxCellについて /やや (18/04/17(Tue) 14:13) #87157
│            └ Re[8]: DataGridViewCheckBoxCellについて /MTK (18/04/17(Tue) 16:51) #87158
Re[1]: DataGridViewCheckBoxCellについて /魔界の仮面弁士 (18/04/18(Wed) 09:46) #87160
  └ Re[2]: DataGridViewCheckBoxCellについて /MTK (18/04/18(Wed) 16:45) #87165 解決済み


親記事 / ▼[ 87124 ] ▼[ 87160 ]
■87121 / 親階層)  DataGridViewCheckBoxCellについて
□投稿者/ MTK (52回)-(2018/04/13(Fri) 14:19:50)

分類:[C#] 

お世話になります。

DataGridViewの1行目にチェックボックスを設定するため、フォームのロード時にDataGridViewCheckBoxCellを設定しています。
きちんと1行目にチェックボックスが出るようになったのですが、チェックボックスの大きさが思いの外小さかったため、
チェックボックスだけでなくセルをクリックしても、チェックが入るようにしたいと思い、以下のCellClickイベントを追加しました。


private void GridCellClick(object sender, DataGridViewCellEventArgs e)
{
	// 1行目がクリックされた場合のみ
	if (this.changeReceive && e.RowIndex == 0)
	{
		// イベント受取を停止
		this.changeReceive = false;
		
		// チェックを反転
		this.dataGridView[e.ColumnIndex, e.RowIndex].Value = !(bool)this.dataGridView[e.ColumnIndex, e.RowIndex].Value;

		// イベント受取を再開
		this.changeReceive = true;
	}
}

しかしこの実装をすると、チェックボックスがあるセルを押してからフォーカスを外さなければ、チェックのONOFFが切り替わりません。
Refresh や CommitEdit メソッドも呼んでみましたがダメでした。
何か特別な方法が必要なのでしょうか?

[ □ Tree ] 返信 編集キー/

▲[ 87121 ] / ▼[ 87125 ]
■87124 / 1階層)  Re[1]: DataGridViewCheckBoxCellについて
□投稿者/ Hongliang (633回)-(2018/04/13(Fri) 14:52:19)
.Valueを変更した後、DataGridViewのEndEdit()を呼び出すようにしては。
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87124 ] / ▼[ 87126 ]
■87125 / 2階層)  Re[2]: DataGridViewCheckBoxCellについて
□投稿者/ MTK (53回)-(2018/04/13(Fri) 15:48:04)
No87124 (Hongliang さん) に返信

回答ありがとうございます。


> .Valueを変更した後、DataGridViewのEndEdit()を呼び出すようにしては。

Value変更 → EndEdit としてみましたが、うまくいきませんでした。

他にも
BeginEdit → Value変更 → EndEdit 

BeginEdit → Value変更 → EndEdit → CommitEdit
も試してみたのですが、どちらもうまくいかないようです。
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87125 ] / ▼[ 87129 ]
■87126 / 3階層)  Re[3]: DataGridViewCheckBoxCellについて
□投稿者/ PANG2 (1回)-(2018/04/13(Fri) 16:06:40)
[ADO.NET] DataGridView 内のデータ編集とそのときのバインドした DataTable の動作
https://blogs.msdn.microsoft.com/jpsql/2013/09/29/ado-net-datagridview-datatable-2120/
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87126 ] / ▼[ 87130 ]
■87129 / 4階層)  Re[4]: DataGridViewCheckBoxCellについて
□投稿者/ MTK (54回)-(2018/04/13(Fri) 17:10:29)
No87126 (PANG2 さん) に返信

回答ありがとうございます。


DataGridViewの変更後は、明示的にカレント行を移動しないと反映されない仕様ということですかね。
となると変更後、フォーカスを移動、もしくは外すという方向でやるしかなさそうですね。
そちらでの対応を考えてみようと思います。
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87129 ] / ▼[ 87131 ]
■87130 / 5階層)  Re[5]: DataGridViewCheckBoxCellについて
□投稿者/ PANG2 (2回)-(2018/04/13(Fri) 17:32:39)
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87130 ] / ▼[ 87157 ]
■87131 / 6階層)  Re[6]: DataGridViewCheckBoxCellについて
□投稿者/ MTK (55回)-(2018/04/13(Fri) 18:10:18)
No87130 (PANG2 さん) に返信

対策1のEndEditについてはHongliangさんにご指摘頂いて試したのですが、できませんでした。
AcceptChanges の実行や 直接 DataRow を更新 については、今回のDataGridViewCheckBoxCellやDataGridViewにそもそも見つかりませんでした。
似たようなものがないか見てみたのですが、私には見つけることができませんでした。
何か方法がありますでしょうか?
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87131 ] / ▼[ 87158 ]
■87157 / 7階層)  Re[7]: DataGridViewCheckBoxCellについて
□投稿者/ やや (7回)-(2018/04/17(Tue) 14:13:52)
2018/04/17(Tue) 14:16:05 編集(投稿者)

No87131 (MTK さん) に返信
> ■No87130 (PANG2 さん) に返信
>
> 対策1のEndEditについてはHongliangさんにご指摘頂いて試したのですが、できませんでした。
> AcceptChanges の実行や 直接 DataRow を更新 については、今回のDataGridViewCheckBoxCellやDataGridViewにそもそも見つかりませんでした。
> 似たようなものがないか見てみたのですが、私には見つけることができませんでした。
> 何か方法がありますでしょうか?

上記の方法はDataTableをDataGridViewにバインドしている場合の解決策と思われます。
バインドをしている場合、this.dataGridView.DataSourceにDataTableのインスタンスアドレスが格納されているはずなので、そちらを参照して試すとうまくいくかもしれません。
バインドではなく、1セルずつ項目を作成している場合は別のアプローチが必要だと思います。
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87157 ] / 返信無し
■87158 / 8階層)  Re[8]: DataGridViewCheckBoxCellについて
□投稿者/ MTK (56回)-(2018/04/17(Tue) 16:51:23)
No87157 (やや さん) に返信

> 上記の方法はDataTableをDataGridViewにバインドしている場合の解決策と思われます。
> バインドをしている場合、this.dataGridView.DataSourceにDataTableのインスタンスアドレスが格納されているはずなので、そちらを参照して試すとうまくいくかもしれません。
> バインドではなく、1セルずつ項目を作成している場合は別のアプローチが必要だと思います。

回答ありがとうございます。

今回はバインド等を行っていないため、別のアプローチになりそうです。
スマートな解決方法が見つからず、現状ではセルをクリックした際にフォーカスを外す処理を入れて反映させるようにしているところです。
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87121 ] / ▼[ 87165 ]
■87160 / 1階層)  Re[1]: DataGridViewCheckBoxCellについて
□投稿者/ 魔界の仮面弁士 (1646回)-(2018/04/18(Wed) 09:46:24)
No87121 (MTK さん) に返信
> チェックボックスだけでなくセルをクリックしても、チェックが入るようにしたいと思い、

DataGridViewCheckBoxCell の ContentBounds プロパティが返す範囲を
「チェックボックス部」から、「セル全体」に広げてしまった方が手っ取り早いかも。


public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();

    // 今回の実験対象となる DataGridView
    dgv = new DataGridView() { Dock = DockStyle.Fill };
    dgv.AllowUserToAddRows = false;
    dgv.ColumnCount = 5;
    dgv.RowCount = 10;

    changeReceive = new List<CheckBox>();
    for (int c = 0; c < dgv.ColumnCount; c++)
    {
      // No87121 「DataGridViewの1行目にチェックボックスを設定する」
      dgv.Columns[c].HeaderText = "列" + c;
      dgv[c, 0] = new CheckBoxCell();

      // 【デバッグ用】
      // チェックボックスセルの状態を
      // 確認するためのチェックボックス
      var chk = new CheckBox() { Dock = DockStyle.Top };
      Controls.Add(chk);
      changeReceive.Add(chk);
      chk.BringToFront();
    }
    Controls.Add(dgv);
    dgv.BringToFront();

    // 【デバッグ用】
    // DataGridViewCheckBoxCell の状態が変化したら
    // それを CheckBox に伝える
    dgv.CellValueChanged += dgv_CellValueChanged;
  }
  DataGridView dgv;
  List<CheckBox> changeReceive;

  // 【デバッグ用】
  private void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e)
  {
    var dgv = (DataGridView)sender;
    if (e.ColumnIndex >= 0 && e.RowIndex == 0)
    {
      var b = (bool)dgv[e.ColumnIndex, 0].Value;
      changeReceive[e.ColumnIndex].Checked = b;
    }
  }


  #region DataGridViewCheckBoxCell の派生実装
  private class CheckBoxCell : DataGridViewCheckBoxCell
  {
    public CheckBoxCell() : this(false) { }
    public CheckBoxCell(bool threeState) : base(threeState)
    {
      // データソースの既定の型を System.Boolean にしておく
      TrueValue = true;
      FalseValue = Value = false;
    }
    /// <summary>セルの余白部でもチェックボックスを反応させる</summary>
    protected override Rectangle GetContentBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
    {
      // return base.GetContentBounds(graphics, cellStyle, rowIndex);
      var cdr = base.DataGridView.GetCellDisplayRectangle(base.ColumnIndex, rowIndex, false);
      return new Rectangle(0, 0, cdr.Width, cdr.Height);
    }
    /// <summary>クリックされたら即時にチェックボックスの状態を変更</summary>
    protected override void OnContentClick(DataGridViewCellEventArgs e)
    {
      base.OnContentClick(e);
      base.DataGridView.EndEdit();
    }
    /// <summary>チェックボックスをダブルクリックした場合にも反応させる</summary>
    protected override void OnContentDoubleClick(DataGridViewCellEventArgs e)
    {
      // base.OnContentDoubleClick(e);
      this.OnContentClick(e);
    }
  }
  #endregion
}
[ 親 87121 / □ Tree ] 返信 編集キー/

▲[ 87160 ] / 返信無し
■87165 / 2階層)  Re[2]: DataGridViewCheckBoxCellについて
□投稿者/ MTK (57回)-(2018/04/18(Wed) 16:45:54)
No87160 (魔界の仮面弁士 さん) に返信

回答ありがとうございます。


> DataGridViewCheckBoxCell の ContentBounds プロパティが返す範囲を
> 「チェックボックス部」から、「セル全体」に広げてしまった方が手っ取り早いかも。

実際に検証をしてみましたが、まさにこの動きがベストです。
セルクリックをチェックボックスに結びつけるのでは無く、チェックボックスの範囲をセル全体にする というのが目から鱗でした。
それ以外のコードの部分もとても勉強になりました。
ありがとうございました。
解決済み
[ 親 87121 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -