カテゴリー
Software Tech

[C#備忘録]DataGridViewのフォントサイズと行高・列幅の自動調整 (C#) | AmpiTa Project

 Visual StudioでDataGridViewを使うと、標準状態では列幅や行高は一定です。

 そのままでは見づらいのでユーザーが手動で調整することになります。

 しかしながら、項目数が多いと面倒ですし、ちょうど良い幅に何列も合わせていくのは大変です。




ユーザーの期待は自動調整

 ユーザーの期待は、ちょうど良い幅や高さに揃えてくれる自動の機能の搭載だと思います。

 私たちが開発するソフトウェアでも、行高や列幅を自動調整する機能を搭載することは多いです。

 実際に搭載した1つの方法を紹介します。




AutoSizeはチョット違う

 DataGridViewには『AutoSize』という機能があります。

 そのように設定すれば、表示される字数やフォントサイズに合わせて調整してくれます。

 ただし、手動調整に対応しなくなります。従って『この列は見えなくても良い』と思って狭くしようとしても、それができません。




フォントサイズ+10

 DataGridViewの『AutoSize』では、行の高さを『Font.Size』より9ポイント多い数値で調整しています。

 それに倣い、私たちのプログラム上では10ポイント多い数値で設定しています。

 下の例は、変数の使い方や出現順は説明用に書き換えていますが、概ね実装されているコードと同じです。

int intRowHeight= Int32.Parse(dataGridView1.Font.Size.ToString()) + 10;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
    dataGridView1.Rows[i].Height = intRowHeight;
}

 フォントサイズを取得し、それに10を足した数を intRowHeight という変数に代入しています。これが行の高さになります。

 dataGridViewの行数を取得し、 for を使って行番号 0 から行数分だけ処理を実施します。

 for の繰り返し処理の中で、各行の Height を intRowHeight という変数の値に設定していきます。

 何万行というグリッド表示になると、かなり重い処理になるのでもっとスマートな方法を考えた方が良いかもしれません。
 姑息的ですが、処理前に下記コードを入れています。

dataGridView1.Visible = false;
this.Enabled = false;




スクロールバーが消える現象

 自動的に行高・列幅を調整すると、その後にdataGridViewのスクロールバーが消えるという現象が起こります。

 いくつかの実験でわかりましたが、フォーム自体を編集不可にする『this.Enabled』を『false』にするのは良いですが、それを『true』に戻す前に、『dataGridView1.Visible』を『true』に戻さないと、スクロールバーが消えるようです。

 下記が正しい記述です。

dataGridView1.Visible = true;
this.Enabled = true;

 先に『this.Enabled』を『true』にしてから『dataGridView1.Visible』を『true』した場合に、スクロールバーが表示されないことが確認できています。上記コードの2行を入れ替えるとNGです。


 『true』にする指示があるので、その前に『false』の指示があるはずですが、この『false』の順番はどちらでも問題ないようです。
 下記の2つのコードを記述しましたが、結果に影響は出ませんでした。

dataGridView1.Visible = false;
this.Enabled = false;
this.Enabled = false;
dataGridView1.Visible = false;

 タブコントロールを使っている場合は、dataGridViewのあるタブにフォーカスが無いと処理できないようです。
 このタブの選択問題は他でも生じており、参照すべきデータが参照できないなどの弊害が生じていますので、処理前に下記のように『SelectedIndex』を設定する記述を入れる必要があります。

tabControl1.SelectedIndex = 0;

 この、タブコントロールの『SelectedIndex』の調整と、dataGridViewの表示を戻す『dataGridView1.Visible』の記述位置の調整により、タブコントロール上のDataGridViewが1つのときは、今のところ問題なく動作しています。

 ただし、複数のタブコントロールにあるDataGridViewを制御しようとすると上手くいきません。
 姑息的な手段として、タブ1つずつ処理する下記のようなコードを書くとスクロールバー消失現象は回避できました。

tabControl1.SelectedIndex = 2;
dataGridView2.Visible = true;
this.Enabled = true;
this.Enabled = false;
tabControl1.SelectedIndex = 1;
dataGridView1.Visible = true;
this.Enabled = true;

 総合的に考えると『this.Enabled = false』を使うシーンは限定すべきであることがわかりました。

 DataGridViewを明示的に操作していなくても、DataSourceでつながっている先のDataTableを操作することによってDataGridViewに変化が加わり、それが『this.Enabled = false』の状況下で起こるとスクロールバーが消失してしまいます。

 タブコントロールを使う場合は初期設定など複雑になる前のシンプルな場合に限り『this.Enabled = false』を使うようにしています。




列幅はAutoSizeから取得

 列幅はAutoSizeから取得し、設定しています。

intColumns = dataGridView1.ColumnCount;
int[] intColumnsWidth = new int[intColumns];
dataGridView1.AutoSizeColumnsMode = 
    DataGridViewAutoSizeColumnsMode.AllCells;
for (i = 0; i < intColumns ; i++)
{
    intColumnsWidth[i] = dataGridView1.Columns[i].Width;
}
dataGridView1.AutoSizeColumnsMode =
    DataGridViewAutoSizeColumnsMode.None;
for (i= 0; i< intColumns ; i++)
{
    dataGridView1.Columns[i].Width = intColumnsWidth[i];
}            

 冒頭では簡単のためにカラム数を変数 intColumns に入れています。
 intColumnsWidth 変数を宣言し、その数はカラム数分だけ欲しいので intColumns から取得します。

 dataGridViewのカラム幅モードを AutoSize にします。
 AutoSizeで各列幅が自動設定された状態を記録します。列番号 0 から列数分だけ for で巡り、全列の幅を記録します。

 列幅を任意設定できるように dataGridViewのカラム幅モードを None にします。

 続いて列番号 0 から列数分だけ for で巡り、各列番号毎に記録しておいた列幅を設定していきます。

 この処理は列数の分だけなので、多くても100などの比較的少ない数字だと思いますが、AutoSizeで列幅を取得する際に処理が重くなる可能性があります。




処理実行

 上述の方法で自動調整を行うと、各列の文字は先頭から末尾まですべて見えるようになります。

 DataGridViewの標準状態が列幅100で均等なので、自動調整後の視認性に違いは歴然です。




フォントサイズ変更時

 フォントサイズの変更を実施した際にも行高や列幅の自動調整は期待されるところです。

 フォントサイズの変更方法です。
 例えば下記コードであれば現在よりも2ポイント大きいフォントサイズになります。

 このようなコードを実施後に、先述の行高・列幅の自動調整機能を実施して見た目をスッキリさせます。

dataGridView1.Font = 
    new Font(
        dataGridView1.Font.FontFamily, 
        Int32.Parse(dataGridView1.Font.Size.ToString()) + 2
    );



おわりに

 プロのプログラマーさんであれば、少しでも処理を短くし、かつ、処理不能が起こりにくい論理的なコードを書くと思いますが、私たちはD.I.Y.的なプログラミングなので、素人っぽい雑さがあります。

 このページは私たちの備忘録も兼ねる感じになりそうなので、ときどき見直したいと思います。