DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridViewで、Cellの背景色を変えるには?

環境/言語:[WindowsXP, C#, Framework2.0]
分類:[.NET]

お世話になります。
DataGridViewのDataSourceに、DataTable(A) を設定した後、そのAの内容によって
特定CellのBackColorを変更するプログラミングをしております。

あるFromのコンストラクタで、下記一連のコードを実行すると
DataGirdViewにデータのリスト(Aの内容)は表示されるのですが
CellのBackColorがデフォルトの白のままです。

試しに、DataGridView の DataGridViewColumn(C) の DefaultCellStyle の
BackColorを変えて実行したところ、C列のBackColorは変わりました。
優先順位でいうと、Cell のスタイルが最も高いはずですが、コンストラクタでは
変更されないのは、何故なのでしょうか。(何か勘違いをしているのでしょうか)
コンストラクタ以外では、Cell の色は希望通りに変更されます。

対応策を教えて頂ければ幸いです。
宜しく御願い致します。

// コンストラクタ
public Form1( ) {
DataTable dtA = new DataTable( );
dtA.Columns.Add( "Test1", typeof( string ) ) ;
dtA.Columns.Add( "Test2", typeof( string ) ) ;
dtA.Columns.Add( "Test3", typeof( string ) ) ;

dtA.Rows.Add( new object[]{ "001","Name1","1" } );
dtA.Rows.Add( new object[]{ "002","Name2","2" } );
dtA.Rows.Add( new object[]{ "003","Name3","3" } );

DataGridViewTextBoxColumn clm1 = new DataGridViewTextBoxColumn( );
DataGridViewTextBoxColumn clm2 = new DataGridViewTextBoxColumn( );
DataGridViewTextBoxColumn clm3 = new DataGridViewTextBoxColumn( );

clm1.DataPropertyName = "Test1";
clm2.DataPropertyName = "Test2";
clm3.DataPropertyName = "Test3";

// ↓対象のDataGridView
this.dataGridView2.Columns.Clear( );
this.dataGridView2.Columns.Add( clm1 );
this.dataGridView2.Columns.Add( clm2 );
this.dataGridView2.Columns.Add( clm3 );
this.dataGridView2.DataSource = dt2;

// ↓これが効かない。コンストラクタ以外では、色は変わります。
dataGridView2[ 1, 1 ].Style.BackColor = Color.Aqua;
}
データバインディングが完了する前にセルスタイルを変更したということではないでしょうか。データバインディング完了後にセルスタイルを変更するようにしてみてください。
管理人様

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

DataGridView の DataBindingComplete イベントに、Cellのバックカラーを変える
コードを記載したら、色が変わってくれました。

バインディングが完了していなかったのですね (@_@)
コンストラクタでの記載でそうなったというより、1発目のバインド処理は
以降のバインド処理よりも、多少時間が掛かってしまうものなのでしょうか。

本当にありがとうございました。助かりました。
解決済み!
■No22403に返信(末さんの記事)
> CellのBackColorがデフォルトの白のままです。
既定値は Color.White ではなく、SystemColors.Window だったかと思います。


> // ↓これが効かない。コンストラクタ以外では、色は変わります。
コンストラクタではなく、Load イベント等に移動してください。

コンストラクタの時点では、IsHandleCreated プロパティはまだ
false の状態であるため、データバインド系の処理が、うまく連動
しない事があります。(スクロールバーが表示されなかったり)


ちなみに、フォームに直接貼るのでなく、TabControl などを利用している
場合も注意が必要です。タブページは、最初に表示されるまでコントロールが
生成されない仕様になっているため、タブを一度もクリックしていない状態で、
その上にあるコントロールにデータバインドすると、期待動作しません。

こちらの問題については、Form_Load  などで
   tabPage2.Visible = true;   // Show メソッドでも良いかも。
などと書いておく事で対応できます。蛇足までに。


> dataGridView2[ 1, 1 ].Style.BackColor = Color.Aqua;
セルのスタイルを個別変更する方法の場合、ソート等が行われた場合に
元の色にリセットされてしまいます。ソートされた場合などにも
対応させるのであれば、CellFormatting イベントを用いて
  if (e.Valueやe.RowIndex による判定)
  {
     e.CellStyle.BackColor = Color.Aqua;
  }
などとした方が良いかも知れません。



もし、セルのスタイルを個別変更する方法を採用する場合、

* それぞれのセルに、.Style.BackColor を個別に設定するのではなく、
  事前に用意しておいた共通のスタイルを .Style に割り当てる。

* スタイルは親要素(行や列など)から継承される物なので、
  セルの Style プロパティを得る前に、HasStyle プロパティ や
  InheritedStyle プロパティを併用して、余計なセル設定を
  増やさないようにする。

などといった点にも気を配っておくと良いかも知れません。

[Windows フォーム DataGridView コントロールを拡張するための推奨される手順]
http://msdn.microsoft.com/ja-jp/library/ha5xt0d9%28VS.80%29.aspx
魔界の仮面弁士様

色々とご教授下さいまして、有難うございます。
一発目のバインド処理は時間が掛かる?と簡単に考えていた僕は一体。

実は、今回の質問は、コンストラクタに記載したバインディングが
正常に動かない件になっておりますが、実際の流れは異なりまして
コンストラクタでの記載はしておりません。
この点、申し訳ありませんでした。
(同じ現象がコンストラクタで発生したため、原因は同一と考え、質問しやすい方で立てさせて頂きました)

DataGridView が貼り付けられている UserControl のインスタンス(A)を、プログラム起動時に生成しておき
メニューがクリックされた地点で、メインになる Form の Panel に、Aを貼り付けて表示しております。

流れは以下です。
→ システム起動時に、A のインスタンスを生成。DataGridView の列(DataGridViewColumn)はコンストラクタで追加している。
→ メニューを押下する。
→ A の DataGridView に対し、データバインド、Cell色を変える関数を実行。
→ A を メインになる From の Panel に貼り付けて表示する。

DataGridView は、UserControl に直接貼り付けており、TabControl を介しておりません。
しかし、現象としては、TabControl に貼り付けた場合と同じになりますので(一回目の表示以降は正常に動いていた)
UserControl も、インスタンスを生成しただけでは、配下の DataGridView のハンドルを生成していなかったのかと考えられます。

セルスタイルの指定方法についても、詳しく教えて下さいまして
有難うございます。とても勉強になりました。
BackColor 以外のスタイルも指定しておりますので、Styleで割り当てるよう修正します。
本当に有難うございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板