none
dataGridView のColumnHeaders Font Size設定について RRS feed

  • 質問

  • 皆さん、お世話になります。

    早速ですが、質問をさせてください。

    tabControl に配置した dataGridView のプロパティー
    ColumnHeadersDefaultCellStyleのFont Size を設定しても
    プロジェクトを開き直すと先に設定した Font Size が
    tabControlのプロパティーに設定しているFont Sizeに変更
    されてしまいます。

    バグのため、自分で再設定をして回避との記述も見かけました
    が、配置の手順によっては、この問題が生じないケースも確認
    しています。
    本当のところはどうなのでしょうか?

    また、バグを前提に再設定をトライしてみましたが、
    dataGridView5.ColumnHeadersDefaultCellStyle.Font.Size は
    読み取り専用で設定できません。
    設定箇所が間違っているようですが、正しい再設定の方法は
    どうすれば宜しいのでしょうか。

    経験豊富な方々に、ご教授願えないかと質問させて頂きました。

    どうぞ、よろしくお願いいたします。

    2010年7月22日 6:47

回答

  • まず、フォントサイズの変更の仕方についてですが、
    以下の MSDN にある通り、フォントごと置き換える必要があります。

    Control.Font プロパティ
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.font(VS.71).aspx

    たとえば次のようなコードでサイズを変更できます。

    var oldFont = dataGridView5.ColumnHeadersDefaultCellStyle.Font;
    var newFont = new Font(oldFont.FontFamily, 新しいサイズ, oldFont.Style);
    dataGridView5.ColumnHeadersDefaultCellStyle.Font = newFont;

    また、書かれた現象はバグによるものと考えています(「(誤りのある)設計による」場合も含みます)。
    フィードバックも随分昔になされているのですが、完全に放置されているようです。

    ColumnHeaderDefaultCellStyle font property reverts to Form's default font.
    http://connect.microsoft.com/VisualStudio/feedback/details/109451/columnheaderdefaultcellstyle-font-property-reverts-to-forms-default-font#details

    原因について改めて調べてみると、アンビエントの処理に不完全な部分があるようでした(アンビエントについては冒頭の MSDN を参照してください)。
    井上さんのおっしゃる問題が生じないケースですが、親コントロールのフォントが Control.DefaultFont のままの場合ではないかと思われます(親コントロールのフォントが変更されないか、子コントロールに変更を通知しない場合)。

    とりあえず、以下のような派生クラスでこの問題を回避できましたので、一度ご確認いただければと思います。

    public class DataGridViewFix : DataGridView
    {
        public DataGridViewFix()
        {
            this.ColumnHeadersDefaultCellStyleChanged +=
                new EventHandler
                    (DataGridViewFix_ColumnHeadersDefaultCellStyleChanged);
        }

        private DataGridViewCellStyle _oldColumnHeadersDefaultCellStyle;

        private void DataGridViewFix_ColumnHeadersDefaultCellStyleChanged(
            object sender, EventArgs e)
        {
            var newStyle = this.ColumnHeadersDefaultCellStyle;

            if (_oldColumnHeadersDefaultCellStyle == null
                || _oldColumnHeadersDefaultCellStyle.Font != newStyle.Font)
            {
                // ColumnHeadersDefaultCellStyle プロパティへの代入による
                // フォントの変化では、アンビエント状態がリセットされないため、
                // Font プロパティの再設定によりアンビエント状態を更新させる。
                newStyle.Font = null;
                newStyle.Font = newStyle.Font;
            }

            _oldColumnHeadersDefaultCellStyle = newStyle;
        }
    }

    • 編集済み TH01 2010年7月22日 11:25 少しコード変更
    • 回答の候補に設定 山本春海 2010年7月23日 1:19
    • 回答としてマーク 山本春海 2010年7月29日 2:42
    2010年7月22日 11:10

すべての返信

  • まず、フォントサイズの変更の仕方についてですが、
    以下の MSDN にある通り、フォントごと置き換える必要があります。

    Control.Font プロパティ
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.font(VS.71).aspx

    たとえば次のようなコードでサイズを変更できます。

    var oldFont = dataGridView5.ColumnHeadersDefaultCellStyle.Font;
    var newFont = new Font(oldFont.FontFamily, 新しいサイズ, oldFont.Style);
    dataGridView5.ColumnHeadersDefaultCellStyle.Font = newFont;

    また、書かれた現象はバグによるものと考えています(「(誤りのある)設計による」場合も含みます)。
    フィードバックも随分昔になされているのですが、完全に放置されているようです。

    ColumnHeaderDefaultCellStyle font property reverts to Form's default font.
    http://connect.microsoft.com/VisualStudio/feedback/details/109451/columnheaderdefaultcellstyle-font-property-reverts-to-forms-default-font#details

    原因について改めて調べてみると、アンビエントの処理に不完全な部分があるようでした(アンビエントについては冒頭の MSDN を参照してください)。
    井上さんのおっしゃる問題が生じないケースですが、親コントロールのフォントが Control.DefaultFont のままの場合ではないかと思われます(親コントロールのフォントが変更されないか、子コントロールに変更を通知しない場合)。

    とりあえず、以下のような派生クラスでこの問題を回避できましたので、一度ご確認いただければと思います。

    public class DataGridViewFix : DataGridView
    {
        public DataGridViewFix()
        {
            this.ColumnHeadersDefaultCellStyleChanged +=
                new EventHandler
                    (DataGridViewFix_ColumnHeadersDefaultCellStyleChanged);
        }

        private DataGridViewCellStyle _oldColumnHeadersDefaultCellStyle;

        private void DataGridViewFix_ColumnHeadersDefaultCellStyleChanged(
            object sender, EventArgs e)
        {
            var newStyle = this.ColumnHeadersDefaultCellStyle;

            if (_oldColumnHeadersDefaultCellStyle == null
                || _oldColumnHeadersDefaultCellStyle.Font != newStyle.Font)
            {
                // ColumnHeadersDefaultCellStyle プロパティへの代入による
                // フォントの変化では、アンビエント状態がリセットされないため、
                // Font プロパティの再設定によりアンビエント状態を更新させる。
                newStyle.Font = null;
                newStyle.Font = newStyle.Font;
            }

            _oldColumnHeadersDefaultCellStyle = newStyle;
        }
    }

    • 編集済み TH01 2010年7月22日 11:25 少しコード変更
    • 回答の候補に設定 山本春海 2010年7月23日 1:19
    • 回答としてマーク 山本春海 2010年7月29日 2:42
    2010年7月22日 11:10
  • 外していたらすみませんが・・・
    もしかして、DataGridView.EnableHeadersVisualStyles が True になっているとか。


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2010年7月22日 11:55
    モデレータ
  • TH01 さん、早速ご教授頂き有難うございます。

    Fontサイズの変更は、Font毎に置き換える必要がある事が分かりました。

    お教え頂いた方法で、旨く対応する事ができました。

    所で、問題が生じないケースですが、親コントロールのフォントは
    変更しています。
    同じ親コントロールに配置したdataGridViewで問題が生じる場合と
    そうでない場合が確認されています。
    仰っている「子コントロールに変更を通知しない場合」ですが、
    「通知しない」ように設定する事ができるのでしょうか?

    次に、派生クラスで問題を回避する方法をお教えくださいましたが、
    この辺りは勉強中で、残念ながら今の私の力では内容を十分理解する
    事ができません。確認の結果をご報告できず申し訳ありません。
    これを教材にして、理解できるよう努力してみたいと思っています。

    色々と、有難うございました。
    今後とも、よろしくお願いいたします。

    2010年7月22日 17:55
  • ひらぽんさん、有難うございます。

    確かに DataGridView.EnableHeadersVisualStyles が True になっていました
    ので、これをfalse に変えるなど、色々試してみましたが、見かけ上、変化は
    有りませんでした。

    とりあえず、TH01 さんに教えて頂いた方法で、Form Load 時に再セットする
    方法で対応しました。

    また、よろしくお願いいたします。

    2010年7月22日 17:56
  • 実行時に設定する方法が一番シンプルだと思うので、蛇足になります。

    > 確認の結果をご報告できず申し訳ありません。

    一応、確認手順をお知らせします。

    1. 新規プロジェクトを作成
    2. Form1 のフォントを変更
    3. Form1 の class 定義の後に DataGridViewFix のコードを貼り付ける。
    4. コンパイル
    5. ツールボックスに DataGridViewFix が表示されるので、それを Form1 に配置する。
    6. 配置した DataGridView に列を追加(確認用)
    7. ColumnHeadersDefaultCellStyle のフォントを変更

    井上さんが作成されているプロジェクトでの確認方法は次の通りです。

    1. 現在のソースをバックアップ(以下の手順でおかしくなった場合に戻せるように)
    2. DataGridViewFix のコードを同じ名前空間に張り付ける。
    3. .Designer.cs を開く
    4. "System.Windows.Forms.DataGridView" という箇所をすべて "DataGridViewFix" に置き換える

    本当は継承しない対策があれば良かったのですが、この不具合はデザイナー上でも発生するものですので、他の方法は思いつきませんでした。


    > 仰っている「子コントロールに変更を通知しない場合」ですが、
    > 「通知しない」ように設定する事ができるのでしょうか?

    設定ではできないです。
    そのように実装されたコントロールもあるかもしれないと、可能性の話として書きました。
    ただ、同じ親でも結果が異なるということですので、この線はないですね。

    .Designer.cs では、問題が生じている方については、次のようなコードになっていると思います(抜粋)。
    問題ない方は、これとは異なる内容でしょうか?
    問題がでない状況をいろいろ想像してみましたが、わかりませんでした。

    System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new ・・・
    this.dataGridView1 = new System.Windows.Forms.DataGridView();
    ・・・
    dataGridViewCellStyle1.Font = new Font(・・・
    ・・・
    this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;

    一応、このバグの詳細を書かせてもらいます。
    症状がでるものとでないものの違いの究明につながればと思います。
    (症状が出ない原因が知りたいのは私だけだったりするかもですが)

    上記抜粋コード内の dataGridViewCellStyle1 は、ColumnHeadersDefaultCellStyle に代入されることではじめて DataGridView と結びつきますが、Font が設定されるのはこの結び付けが行われる前です。
    本来は Font の代入によってアンビエント値ではなくなるのですが、アンビエント状態を管理している内部フラグは DataGridView 側で管理されているため、結びついていない時点でのフォントの設定ではアンビエント状態が正常に管理されません。
    ColumnHeadersDefaultCellStyle への代入によってもこれは変わらないため、結び付けられた DataGridView は ColumnHeadersDefaultCellStyle のフォントがアンビエント状態のままと思っているため、それ以降の親コントロールのフォントの変化を CellStyle に反映してしまいます。

    • 編集済み TH01 2010年7月23日 4:55 少し文章手直し
    2010年7月23日 4:40
  • TH01 さん、こんにちわ!

    この前、お教え頂いてからだいぶ日にちが過ぎてしまい、大変失礼しました。

    その後、お教え頂いた手順で他の資料も参照しながら色々と試してみました。
    しかし知識不足のため、コンパイルの結果ツールボックスにDataGridViewFixが
    表示されるので・・・辺りから旨くいきませんでした。

    また現在のソースを使っての確認も、途中からデザイナーの表示が行われなく
    なってしまい、作業が止まってしまいました。

    折角アドバイスを頂きながら、これを生かせず申し訳ありません。
    そもそも、クラス・派生クラスの概念、使い方そのものの理解が不十分な現状で
    あり、この辺りをもう少し勉強して、再度この確認を行ってみようと思っています。

    具体的な疑問・質問が出てきた際には、また質問をさせて頂きたいと思いますので、
    その節にはよろしくお願いいたします。

    それまで、この項はクローズさせて頂きます。
    有難うございました。

    2010年7月29日 7:32