
前提・実現したいこと
C#でWindowsFormアプリケーションを開発しています。
DataGridViewに色をつけたいです。
CellPaintingイベントで、ForeColorで色を変更してみました。
1回だけなら問題なしですが、DefaultCellStyleを2回変更すると描画処理が終わりません。
どうして無限ループになるのか、いまいちわからずもやもやしています。
すっきりしたいです。
発生している問題・エラーメッセージ
再表示が無限ループする。
該当のソースコード
ループしない private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex < 0) return; ((DataGridView)sender).DefaultCellStyle.ForeColor = Color.Turquoise; }
無限ループ private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex < 0) return; ((DataGridView)sender).DefaultCellStyle.ForeColor = Color.Crimson; ((DataGridView)sender).DefaultCellStyle.ForeColor = Color.Turquoise; }
ループしない private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex < 0) return; e.CellStyle.ForeColor = Color.Crimson; e.CellStyle.ForeColor = Color.Turquoise; }
補足情報(FW/ツールのバージョンなど)
Visual Studio 2015 Pro
Windows Form Applacation
C#
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。


退会済みユーザー
2018/03/19 04:26 編集

回答1件
0
ベストアンサー
コントロールのデフォルトの描画処理では達成できないような描画処理を実装する方法をオーナードローといったりすると思います。それは「今からコントロールを描画します!」というイベントに対するハンドラーを定義することで達成します。
さて「今から自分自身を描画します」というイベント(本件ではCellPaintingイベントということになりましょうか)がいつ発生するかというと、理屈からいって「コントロールの外観に変化がおきるような変更が起こった時」ということになります。
さて、DataGridViewのDefaultCellStyle.ForeColorはセルの前景色を意味するのでこの値が変化すると自動的にCellPaintingイベントが発生し再描画が行われるようになっています。
それを踏まえて・・・
- (A)最初のコード
コントロールのDefaultCellStyle.ForeColorを変更しているためdataGridView_CellPaintingメソッドの実行中に再びCellPaintingイベントが起きてしまいます。ただ、一度Color.Turquoiseの値を設定した後ではCellPaintingイベント処理中に再度同じ色を設定しても「色の変化」は起きないため無限ループになりません。
- (B)次のコード
外観に影響を与えるプロパティーを描画中に複数回変更するということは「再描画処理中に必ずCellPainingイベントを発火させる」ことになり、再描画がいつまでたっても完了しなくなります。
- (C)最後のコード
外観に影響を与えるプロパティーを変更しておらず、単にイベントオブジェクトの中にある「今回の描画における前景色、背景色を変更しているだけ」のためCellPaintingイベントが発生しません。
一般にイベントハンドラーの中でそのイベントが発生する原因になるようなことを再度行うのは避けるべきです。無限ループになってしまいますから。描画に関しては「外観に影響を及ぼす情報を変更するのは描画処理以外の場所ですべきこと」だと思ってください。
追記:自分にも曖昧な点があるのでちょっと調べてみました。
C#
1private Dictionary<object, string> dict = new Dictionary<object, string>(); 2private int idCount = 1; 3 4private string id(object o) { 5 if (!dict.ContainsKey(o)) { 6 dict[o] = string.Format("#{0:X2}", idCount++); 7 } 8 return dict[o]; 9} 10bool dumped=false; 11 12private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { 13 if (!dumped) { 14 foreach (DataGridViewRow row in dataGridView1.Rows) { 15 string s = ""; 16 foreach (DataGridViewCell cc in row.Cells) { 17 s += $" [{cc.RowIndex,2:D},{cc.ColumnIndex,2:D}] Cell={id(cc)}/Cell.Style={id(cc.Style)}"; 18 } 19 Console.WriteLine(s); 20 } 21 dumped = true; 22 } 23 int ri = e.RowIndex; 24 int ci = e.ColumnIndex; 25 Console.WriteLine($"[{ri,2:D}, {ci,2:D}] : CellStyle={id(e.CellStyle)}"); 26 //e.CellStyle.ForeColor = Color.Black; //(D) 27 //e.CellStyle.BackColor = Color.Yellow; //(D) 28 //dataGridView1.DefaultCellStyle.ForeColor = Color.Red; //(E) 29 //dataGridView1.DefaultCellStyle.BackColor = Color.Blue;//(E) 30}
上記を2x2のDataGridViewに対して動かすと初期画面描画時には次のようになりました。
行・列のインデックスが-1になっているところは多分ヘッダー部分ではないかと想像します(ちゃんとわかってません)
着目してほしいのはDataGridViewCellのStyleプロパティオブジェクトの値はEventArgのCellStyleオブジェクトと同一ではないという点です。
[ 0, 0] Cell=#01/Cell.Style=#02 [ 0, 1] Cell=#03/Cell.Style=#02 [ 1, 0] Cell=#04/Cell.Style=#02 [ 1, 1] Cell=#05/Cell.Style=#02 [-1, -1] : CellStyle=#06 [-1, 0] : CellStyle=#06 [-1, 1] : CellStyle=#06 [ 0, -1] : CellStyle=#06 [ 0, 0] : CellStyle=#07 [ 0, 1] : CellStyle=#07 [ 1, -1] : CellStyle=#06 [ 1, 0] : CellStyle=#07 [ 1, 1] : CellStyle=#07
(D)をアンコメントする(CellPainingの中でEventArgのCellStyleを変更する)と、
[ 0, 0] Cell=#01/Cell.Style=#02 [ 0, 1] Cell=#03/Cell.Style=#02 [ 1, 0] Cell=#04/Cell.Style=#02 [ 1, 1] Cell=#05/Cell.Style=#02 [-1, -1] : CellStyle=#06 [-1, 0] : CellStyle=#07 <- [-1, 1] : CellStyle=#07 <- [ 0, -1] : CellStyle=#08 <- [ 0, 0] : CellStyle=#09 <- [ 0, 1] : CellStyle=#09 <- [ 1, -1] : CellStyle=#0A <- [ 1, 0] : CellStyle=#0B <- [ 1, 1] : CellStyle=#0B <-
さらに(E)をアンコメントする(CellPainingの中でDefaultCellStyleを変更する)と、
[ 0, 0] Cell=#01/Cell.Style=#02 [ 0, 1] Cell=#03/Cell.Style=#02 [ 1, 0] Cell=#04/Cell.Style=#02 [ 1, 1] Cell=#05/Cell.Style=#02 [-1, -1] : CellStyle=#06 [-1, 0] : CellStyle=#07 [-1, 1] : CellStyle=#07 [ 0, -1] : CellStyle=#08 [ 0, 0] : CellStyle=#09 [ 0, 1] : CellStyle=#09 [ 1, -1] : CellStyle=#0A [ 1, 0] : CellStyle=#0B [ 1, 1] : CellStyle=#0B [-1, -1] : CellStyle=#0C [-1, 0] : CellStyle=#0D [-1, 1] : CellStyle=#0D [ 0, -1] : CellStyle=#0E [ 0, 0] : CellStyle=#0F [ 0, 1] : CellStyle=#0F [ 1, -1] : CellStyle=#10 [ 1, 0] : CellStyle=#11 [ 1, 1] : CellStyle=#11
こんな具合になります。上記結果を元の回答コメントに照らして考えてみるといかがでしょう?
投稿2018/03/19 04:53
編集2018/03/19 08:30総合スコア18404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/20 06:08

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。