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

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

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

Re[2]: セル単位でのcellstyleの変更について


(過去ログ 52 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■28699 / inTopicNo.1)  セル単位でのcellstyleの変更について
  
□投稿者/ 見習いPG (14回)-(2008/11/29(Sat) 06:37:45)

分類:[C#] 

お世話になっております。
環境:C# 2005 VisualStadio

datagridviewのセル単位でのcellstyleの変更をしようとしていまして、
以下のようなコードを打ち込んだのですが、

//toolStripComboBox2.Textには"MS Pゴシック"等の文字列が入っています
//toolStripComboBox1.Textには"9"等の数字(string型)が入っています

//フォント体の変更
dataGridView1[0, 0].Style.Font = new Font(toolStripComboBox2.Text, dataGridView1[0, 0].Style.Font.Size);

//フォントサイズの変更
dataGridView1[0, 0].Style.Font = new Font(dataGridView1[0, 0].Style.Font.Name,
                              int.Parse(toolStripComboBox1.Text));


dataGridView1[0, 0].Style.Font.SizeとdataGridView1[0, 0].Style.Font.Nameで、null例外が発生します。
なので、Form_loadのイベントでCellStyleを設定すればいいのかなと思い、

dataGridView1.DefaultCellStyle.Font = new Font("MS Pゴシック", 9, FontStyle.Regular);
や
dataGridView1.Font = new Font("MS Pゴシック", 9, FontStyle.Regular);
等、色々調べては試しているのですが、ずっとnullのままです。

フォントサイズの変更だけなら、dataGridView1[0, 0].Style.Font.Name部分をdataGridView1.Font.Name
に書き換えれば、フォントサイズは変更できますが、フォント体が元の設定に戻ってしまいます。

私がやりたい事は、そのセルに設定したフォント体やフォントサイズを保ったまま変更を行っていきたいのです。
最初に、
dataGridView1[0, 0].Style.Font = new Font(toolStripComboBox2.Text, dataGridView1.Font.Size);
を実行すれば、
dataGridView1[0, 0].Style.Font.Nameに"MS Pゴシック"が設定されているので、
dataGridView1[0, 0].Style.Font = new Font(dataGridView1[0, 0].Style.Font.Name,
                              int.Parse(toolStripComboBox1.Text));
でフォント体の状態を保ったまま、フォントサイズの変更が可能ですが、これではフォント体を変更する時、
サイズが元に戻ってしまうので、ダメなのです。

簡潔に言うと、null例外が出るので、セル単位での初期の状態を設定したいのですが、やり方がわかりません。
どうすれば、値が設定できるのか教えて下さい。
宜しくお願い致します。

引用返信 編集キー/
■28705 / inTopicNo.2)  Re[1]: セル単位でのcellstyleの変更について
□投稿者/ 魔界の仮面弁士 (912回)-(2008/11/29(Sat) 10:33:01)
2008/11/29(Sat) 10:49:47 編集(投稿者)

No28699 (見習いPG さん) に返信
> "MS Pゴシック"等の文字列が入っています
"MS Pゴシック" ではなく、
"MS Pゴシック" にしておいた方が良いかと。


> dataGridView1[0, 0].Style.Font.Nameで、null例外が発生します。
フォントが割り当てられていなければ、.Style.Font は null を返しますからね。

現在の設定値を確認する目的であれば、いきなり .Style.Font を参照するのは NG です。
# 説明するとややこしいので、具体的な方法は、後述のコードから読み取ってください。(^^;


> dataGridView1.DefaultCellStyle.Font = new Font("MS Pゴシック", 9, FontStyle.Regular);
> dataGridView1.Font = new Font("MS Pゴシック", 9, FontStyle.Regular);

スタイル設定は、「グリッド全体」「行単位」「奇数行」「列単位」「セル単位」などなど
複数の設定箇所がありますよね。これらの優先順位などを、よく確認してみてください。
http://msdn2.microsoft.com/ja-jp/library/1yef90x0%28VS.80%29.aspx


たとえばこんなコードを書いて、スタイルの関係を確認してみては如何でしょう。

private void Form1_Load(object sender, EventArgs e)
{
  dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
  dataGridView1.AllowUserToAddRows = false;
  dataGridView1.RowCount = 2;
  dataGridView1.ColumnCount = 4;

  DataGridViewCellStyle cs;
  // 1行目の書式を設定
  cs = dataGridView1.Rows[1].DefaultCellStyle;
  cs.BackColor = Color.Red;
  cs.Font = new Font("MS Pゴシック", 12);

  // 0列目の書式を設定
  cs = dataGridView1.Columns[0].DefaultCellStyle;
  cs.BackColor = Color.Yellow;
  cs.Font = new Font("Wingdings", 15);

  // 1行目の1列目の書式を設定
  cs = dataGridView1[1, 1].Style;
  cs.BackColor = Color.Green;
  cs.Font = null;

  // 1行目の2列目の書式を設定
  cs = dataGridView1[2, 1].Style;
  cs.BackColor = Color.Empty;
  cs.Font = new Font("MS 明朝", 9);

  // 1行目の3列目は書式を設定しない
  dataGridView1[3, 1].Style = null;
}

ColorConverter c = new ColorConverter();
FontConverter f = new FontConverter();

// 書式情報を表示
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
  listBox1.Items.Clear();

  DataGridViewCell cell = ((DataGridView)sender)[e.ColumnIndex, e.RowIndex];
  listBox1.Items.Add("=== セルの書式 ===");
  if (!cell.HasStyle)
  {
    listBox1.Items.Add("(セルの書式は");
    listBox1.Items.Add(" 設定されていない)");
  }
  else
  {
    listBox1.Items.Add("Style-Color:" + c.ConvertToString(cell.Style.BackColor));
    listBox1.Items.Add("Style-Font:" + f.ConvertToString(cell.Style.Font));
  }
  listBox1.Items.Add("Inherit-Color:" + c.ConvertToString(cell.InheritedStyle.BackColor));
  listBox1.Items.Add("Inherit-Font:" + f.ConvertToString(cell.InheritedStyle.Font));

  DataGridViewRow row = ((DataGridView)sender).Rows[e.RowIndex];
  listBox1.Items.Add("=== 行の書式 ===");
  if (!row.HasDefaultCellStyle)
  {
    listBox1.Items.Add("(行の書式は");
    listBox1.Items.Add(" 設定されていない)");
  }
  else
  {
    listBox1.Items.Add("Style-Color:" + c.ConvertToString(row.DefaultCellStyle.BackColor));
    listBox1.Items.Add("Style-Font:" + f.ConvertToString(row.DefaultCellStyle.Font));
  }
  listBox1.Items.Add("Inherit-Color:" + c.ConvertToString(row.InheritedStyle.BackColor));
  listBox1.Items.Add("Inherit-Font:" + f.ConvertToString(row.InheritedStyle.Font));

  DataGridViewColumn col = ((DataGridView)sender).Columns[e.ColumnIndex];
  listBox1.Items.Add("=== 列の書式 ===");
  if (!col.HasDefaultCellStyle)
  {
    listBox1.Items.Add("(列の書式は");
    listBox1.Items.Add(" 設定されていない)");
  }
  else
  {
    listBox1.Items.Add("Style-Color:" + c.ConvertToString(col.DefaultCellStyle.BackColor));
    listBox1.Items.Add("Style-Font:" + f.ConvertToString(col.DefaultCellStyle.Font));
  }
  listBox1.Items.Add("Inherit-Color:" + c.ConvertToString(col.InheritedStyle.BackColor));
  listBox1.Items.Add("Inherit-Font:" + f.ConvertToString(col.InheritedStyle.Font));
}
引用返信 編集キー/
■28814 / inTopicNo.3)  Re[2]: セル単位でのcellstyleの変更について
□投稿者/ 見習いPG (15回)-(2008/12/01(Mon) 17:15:23)
2008/12/01(Mon) 17:35:54 編集(投稿者)
2008/12/01(Mon) 17:34:27 編集(投稿者)

No28705 (魔界の仮面弁士 さん) に返信

返答ありがとうございます。
まず、MS公式を見てみましたが、あまり理解できず、魔界さんのコードを実際に書いて確認してみました。
非常に分かりやすく説明して頂いたおかげで、セルスタイルの事がよく理解できました。
本当にありがとうございます。
また、私が今練習しているコードにも当てはめてみて、やりたかった動作ができるのを確認して、
以下の様に理解しましたが、大丈夫でしょうか?

DataGridViewCellStyleクラスでは、"行"や"列"また"セル"に設定される値は独立していて、

dataGridView1.DefaultCellStyle.Font = new Font("MS Pゴシック", 9, FontStyle.Regular);

で、DataGridView全体に対して値を設定しても、"行"や"列"、"セル"単位で値を設定していない為、
dataGridView1[1, 1].Style.Font.Size や dataGridView1.Columns[0].DefaultCellStyle.Font.Name
等で値を参照しようとしても、nullを返してしまう。
つまり、セルや行、列"単位"で設定を、対象の"セル・行・列"の状態を保ったまま変更したいのであれば、
変更を行いたい単位の値を、"セル"、"行"、"列"単位で設定しておかなければならない。

分かりにくい文章でしたら、すいません。
もし間違っていればご指摘頂けると嬉しいです。
引用返信 編集キー/
■28818 / inTopicNo.4)  Re[3]: セル単位でのcellstyleの変更について
□投稿者/ .SHO (261回)-(2008/12/01(Mon) 19:19:22)
No28814 (見習いPG さん) に返信

> 変更を行いたい単位の値を、"セル"、"行"、"列"単位で設定しておかなければならない。

最初にすべて設定しておかなくても、変更が必要になった時に
null かどうかを判断し、null ならデフォルト値を、null じゃなければ
現在値を使用すればいいのではないでしょうか。

引用返信 編集キー/
■28819 / inTopicNo.5)  Re[1]: セル単位でのcellstyleの変更について
□投稿者/ .SHO (262回)-(2008/12/01(Mon) 19:25:25)
No28699 (見習いPG さん) に返信

> //フォント体の変更
> dataGridView1[0, 0].Style.Font = new Font(toolStripComboBox2.Text, dataGridView1[0, 0].Style.Font.Size);
> 
> //フォントサイズの変更
> dataGridView1[0, 0].Style.Font = new Font(dataGridView1[0, 0].Style.Font.Name,
>                               int.Parse(toolStripComboBox1.Text));

作っちゃった方が早そうだ^^;
↓こんな感じです。

//フォント体の変更
if ( dataGridView1[0, 0].Style.Font.Size == null )
    dataGridView1[0, 0].Style.Font = new Font(toolStripComboBox2.Text, 9 );
else
    dataGridView1[0, 0].Style.Font = new Font(toolStripComboBox2.Text, dataGridView1[0, 0].Style.Font.Size);

//フォントサイズの変更
if ( dataGridView1[0, 0].Style.Font.Name == null )
    dataGridView1[0, 0].Style.Font = new Font("MS Pゴシック",
                               int.Parse(toolStripComboBox1.Text));
else
    dataGridView1[0, 0].Style.Font = new Font(dataGridView1[0, 0].Style.Font.Name,
                               int.Parse(toolStripComboBox1.Text));

引用返信 編集キー/
■28821 / inTopicNo.6)  Re[3]: セル単位でのcellstyleの変更について
□投稿者/ 魔界の仮面弁士 (916回)-(2008/12/01(Mon) 19:42:49)
2008/12/01(Mon) 19:49:21 編集(投稿者)

# 長文失礼。

No28814 (見習いPG さん) に返信
> DataGridViewCellStyleクラスでは、"行"や"列"また"セル"に
他にも、"奇数行" などの設定もありますね。また、ヘッダ部/データ部のセルの違いもあります。


> 設定される値は独立していて、
独立しているというか、透過関係にあります。
HTML でいうところのスタイルシートの関係に近いかな。


文章で説明しにくいので…他の物に喩えさせてください。

新規プロジェクトを作成し、Form1 の上に GroupBox を 1 つ貼ってみてください。
そしてその上に、Panel を 2 つ貼ります。

階層関係としては、このような配置となります。

Form1
└groupBox1
 ├panel1
 └panel2

# 以下の説明は、文章で読むと分かりにくいと思うので、
# できれば、実際に開発環境で操作しながら読んでみてください。(^^;


さて、Form1 の BackColor は、既定で "Control" です。
そのため、各コントロールの背景色も、"Control" になっており、
かつ、それらのプロパティは『細字』で表現されています。

ここで、groupBox1 の BackColor を "Yellow" に変更してみてください。
groupBox1 の BackColor プロパティが『太字』で表現されますね。

この時、2 枚の Panel の BackColor もまた、"Yellow" になっています。
しかし、BackColor そのものは『細字』のままであるはずです。


そしてここで、panel2 の方の BackColor に、別の色(例えば "Red")を設定します。
panel2 の BackColor が『太字』に変わるので、再度 "Yellow" を選択しなおします。

このようにすると、それぞれの Panel の BackColor は、
 panel1 … 『細字』の "Yellow"
 panel2 … 『太字』の "Yellow"
となります。どちらも同じ色ですが、一方は「太字」で表記されていますね。

そしてここで、groupBox1 の BackColor を "Blue" にするとどうなるでしょう。
 panel1 … 『細字』の "Blue"
 panel2 … 『太字』の "Yellow"
になるはずです。
panel1 は親の値を引き継ぎますが、panel2 は "Yellow" のままです。

そしてさらに、groupBox1 の BackColor を右クリックして、[リセット]を選択します。
すると panel1 が、親の親であるフォームの設定色に戻り、
 panel1 … 『細字』の "Control"
 panel2 … 『太字』の "Yellow"
という結果に変わります。

------------------------------------------------------

これと同じことが、DataGridView のスタイル設定にも言えます。

Style プロパティに null をセットすると、セルのスタイルはクリアされ、
HasStyle = false の状態になります。この場合、そのセルのスタイルは
上位要素(行やグリッド本体など)の設定が使って処理される事になります。

また、セルに個別のスタイルが割り当てられていた場合であっても、
 .Alignment = DataGridViewContentAlignment.NotSet
 .Font = null
 .BackColor = Color.Empty
などが割り当てられていれば、フォントや背景色など、個々のメンバだけが
上位要素の書式を引き継ぐ事になります。

そして、その引き継いだ値を得るのが、先のサンプルでも利用した
InheritedStyle プロパティ(読取専用)となります。


> 対象の"セル・行・列"の状態を保ったまま変更したいのであれば、
この場合、この「変更」という行為が、それぞれのスタイルに対して
「設定のリセット」なのか「新しい設定の割り当て」なのかを見直し、
かつ、それがセル/行/奇数行/列/グリッド全体など、どの要素に対して
行おうとしているのかを意識するようにしてみてください。

それらを意識した上で、元々の質問 No28699
> セル単位での初期の状態を設定したいのですが
を考えてみると、修正すべき箇所が見えてくるかと思いますよ。


> MS公式を見てみましたが、あまり理解できず
見落とされがちな点があるので、もう少し書かせてください:

セルのスタイルが未設定(null)の時に、Style プロパティを参照すると、
その場で新たなスタイルが割り当てられてしまう点に気をつけてください。

 Console.WriteLine(dataGridView1[1, 1].HasStyle); // この時点で false だとしても、
 Console.WriteLine(dataGridView1[1, 1].Style) ; // ここで Style を取得してしまうと
 Console.WriteLine(dataGridView1[1, 1].HasStyle); // この時点で true に変化してしまう。


スタイル設定の増加はパフォーマンスに影響を与えますので、セル数が多い場合は注意してください。
たとえば、先の No28705 にも
>> 現在の設定値を確認する目的であれば、いきなり .Style.Font を参照するのは NG です。
と書いたように
 if ( dataGridView1[col, row].Style.Font == null )
のような判定は、できる限り避けるようにする必要があります。設定値の確認には、
InheritedStyle プロパティや HasStyle プロパティを使うようにしましょう。


また、各セルに対するスタイル設定を共有することも検討してみてください。
たとえば、こんな感じで…。

DataGridViewCellStyle blackStyle = new DataGridViewCellStyle();
DataGridViewCellStyle greenStyle = new DataGridViewCellStyle();
private void Form1_Load(object sender, EventArgs e)
{
 blackStyle.BackColor = blackStyle.SelectionBackColor = Color.Black;
 greenStyle.BackColor = greenStyle.SelectionBackColor = Color.Green;

 dataGridView1.AllowUserToAddRows = false;
 dataGridView1.RowCount = 4;
 dataGridView1.ColumnCount = 4;

 dataGridView1[1, 1].Style = dataGridView1[2, 2].Style = blackStyle;
 dataGridView1[2, 1].Style = dataGridView1[1, 2].Style = greenStyle;
}

private void button1_Click(object sender, EventArgs e)
{
 greenStyle.BackColor = Color.YellowGreen;
 dataGridView1.Invalidate();
}
引用返信 編集キー/
■28966 / inTopicNo.7)  Re[2]: セル単位でのcellstyleの変更について
□投稿者/ 見習いPG (16回)-(2008/12/03(Wed) 08:28:30)
>.SHOさん
返信ありがとうございます。
そうですね、最初私もその方法を取ろうとしたのですが、
セルスタイルを余り理解しないまま進むのはスッキリしないので、あえて使わずにいました。
しかし、魔界さんのおかげでだいぶ理解できたと思うので、現在のコードを余り修正しないで済む
.SHOさんのコードの方向でいこうかと思います。ありがとうございます。


>魔界の仮面弁士さん
なるほど。最初に頂いたサンプルコードの意味が全て理解できました。
私レベルの者に非常分かり易く教えて頂いて、ありがとうございました。


ようやく理解できたので、この辺りで解決とさせて頂きます。
ありがとうございました!
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -