none
DataGridView を使って単純な表を作りたい(後から値を設定したい)。 RRS feed

  • 質問

  • 表には行、列のヘッダーがあり、各セルにはプログラムで計算した値をセットし、見る
    だけの単純なものを作りたいだけです。非バインド モードで良いのかと考えています。

    初期化で、行のヘッダーの表記をするためのxxx.Rows[i].HeaderCell.Value = i.ToString();
     を実行する前にxxx.Rows.Add(row) により、各行が先に確保されていなければならない
    (後先が逆で違和感を感じています。どうでしょう?)ようですが、この時点では、
    まだ値が決まっておらず空白にしています。

    初期化後のプログラムで値が確定してから各セルに値を表示させたいのですが、
    どのようにしたら良いのでしょうか?

    選択もしたくないのですが、xxx.DefaultCellStyle.SelectionBackColor = Color.White;
    などで、見かけ上そうできるとのことですが、行のヘッダーに選択のための横向きの▲が
    残っているせいか、ヘッダーの幅が大きくなっています。
    選択そのものが出来ないようにした方が良いと思いますが、どのようにしたたら良いのでしょうか?
    または、行のヘッダーの幅を小さくするにはどうしたら良いでしょうか?

    感想ですが、編集もしたくない、ソートもしたくない、選択もしたくない、
    ただ、単に表を作るだけが難しいいんですね。

    2010年1月15日 6:19

回答

  • 直接的な回答でなくて申しわけありませんが、DOBON さんのサイトに行けば色々使えそうな Tips があります。

    http://dobon.net/vb/dotnet/datagridview/index.html


    またどのくらいのデータを設定されるのか判りませんが、非バインド モードで

    > xxx.Rows.Add(row)

    は、パフォーマンスが非常に悪いので推奨できません。
    先に空の DataTable を作り、DataTable に値を設定してからバインド(もしくはその逆も可)する方が性能が高いです。

    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月15日 7:01
    モデレータ
  • ListViewが適しているかもしれませんね。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月15日 7:06
    モデレータ
  • > 先に空の DataTable を作り、DataTable に値を設定してからバインド(もしくはその逆も可)する方が性能が高いです。

    参考のため、空データのテーブルを作りバインドするサンプルです。

    private void button1_Click(object sender, EventArgs e)
    {
    	// 一万行の空データをグリッドに設定する
    	DataTable dt = new DataTable();
    	for (int i = 0; i < 5; i++)
    	{
    		dt.Columns.Add();
    	}
    	for (int i = 0; i < 10000; i++)
    	{
    		string[] values = 
    { string.Empty, string.Empty, string.Empty, string.Empty }; dt.Rows.Add(); } dataGridView1.DataSource = dt; }

    あとは

        DataRow(行インデックス)(列インデックス) = 値;

    みたいな感じで、DataTable の方を編集すればいいかと。

    #最近も某所で似たような質問があったな・・・
    • 編集済み ひらぽんModerator 2010年1月15日 7:25 途中で送信してしまいました
    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月15日 7:19
    モデレータ
  • > この部分のコーディングが具体的に分かりませんで、よろしくお願いします。

    たとえばこんな感じになります。全ての行に同じデータを設定するとして・・・

    void method1(DataTable dt)
    {
            // 全ての行に設定
            foreach (DataRow row in dt.Rows)
           {
                row["customerId"] = 1;
                row["name"] = "ひらぽん";
                row["country"] = "Japan";
                row["city"] = "Tokyo"
           }
    }
    > 今回の場合は配列をDataGridViewに表示するという流れで教えてもらえれば助かります。

    配列がどういう形式か判りませんが、二次元配列の場合のサンプルです。
    ちなみにコーディングしただけなので試してません。悪しからず。<(_ _)>

    void method2(DataGridView grid, Array array)
    {
           DataTable dt = new DataTable();
           foreach (Object col in array[0])        {             dt.Columns.Add();        }

           foreach (Array values in array)
           {
                dt.Rows.Add(values);
           }
           grid.DataSource = dt;
    }
    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月18日 3:01
    モデレータ
  • 全て答えている時間がないので、最初の質問だけ回答します。

    1.数値の書式のためのFormatに関して
               
    xxx.DefaultCellStyle.Format = "d";
    xxx.Columns[0].DefaultCellStyle.Format = "d";
    xxx.Columns[0].DefaultCellStyle.Format = "N2";
    などのようにしますが、
    コンパイルは通りますが、実際には何もおこりません。(1000が1,000とならず1000まま)
    どうしたら機能するようになりますか?

    基本的に、列の書式はデザイナで設定します。

    DataGridView コントロールの右上隅にあるスマート タグ グリフをクリック。
    列の編集ダイアログが開いたら設定したい列を選択。
    DefaultCellStyleの編集窓の右側ボタンをクリックして
    CellStyle ビルダ ダイアログを起動。Format を設定します。

    コーディングでやるなら、以下を参照してください。

    http://dobon.net/vb/dotnet/datagrid/columnformat.html

    他の質問に関しては、上記 DOBON さんのところで検索してみてください。

    • 回答としてマーク クサキ 2010年1月21日 9:19
    2010年1月19日 6:01
    モデレータ
  • 1.
    > コンパイルは通りますが、実際には何もおこりません。(1000が1,000とならず1000まま)
    > どうしたら機能するようになりますか?

    値の型が数値の場合はフォーマットされますが、
    値が文字列の "1000" の場合はフォーマットされません。
    grid[0, 0].Value = 1000;   // される
    grid[0, 0].Value = "1000"; // されない
    このことが関係してないでしょうか?

    > また、xxx.Columns[0].DefaultCellStyle. とコーディングした時点で、
    > 候補がポップアップしますが、Alignmentなどはありますが、Formatはありません。

    それはおかしいですね。
    もしかして、たとえば以下の状況に近い話ではないでしょうか?

    DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
    col.MaxInputLength = 100;
    grid.Columns.Add(col);
    grid.Columns[0]. // DataGridViewColumn 型なので MaxInputLength は選択肢にでない。

    > 2.ヘッダーでの Alignment の指定はどうするのでしょうか?

    ヘッダーに対する Alignment 指定でしたら、次のようにします。
    grid.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;

    > 3.選択そのものが出来ないようにするか、ヘッダーの幅を調整することは出来ないのでしょうか。

    行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。

    > 感想ですが、編集もしたくない、ソートもしたくない、選択もしたくない、
    > ただ、単に表を作るだけが難しいいんですね。

    複雑なコントロールなのでいろんなことができますが、確かに最初はとっつきにくいと思います。
    ご質問ではない点も含め、一応、以下にそれぞれについて書かせてもらいます。

    ■編集不可
    grid.ReadOnly = true;
    このほかに、列単位、行単位、セル単位、と、様々な制御ができます。
    CellBeginEdit イベントを使えば、プログラムで制御することもできます。

    ■ソート不可
    grid.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable;

    ■選択不可
    やはり、色の変更での対応がよいと思います。
    var style = grid.Columns[0].DefaultCellStyle;
    style.SelectionBackColor = SystemColors.Window;
    style.SelectionForeColor = SystemColors.WindowText;

    別の方法としては、データの表示処理の最後で
    grid.CurrentCell = null;
    を実行し、CurrentCellChanged イベントハンドラで
    private void grid_CurrentCellChanged(object sender, EventArgs e)
    {
        var grid = sender as DataGridView;
        if (grid == null) return;
        if (grid.CurrentCell != null)
            grid.BeginInvoke(new Action(() => { grid.CurrentCell = null; }));
    }
    とすることで、カレントセルがない状態(=選択セルがない状態)にできます。
    ただし、こうしたところで色変更に勝るメリットはなさそうですが。

    • 回答としてマーク クサキ 2010年1月21日 9:19
    2010年1月19日 7:09
  • デザイナーで列を追加した場合は
    DataTableとの関連付けはどのようにしたら良いですか?
    DataGridView の 「列の編集」 で設定したい列を選択、
    DataPropertyName にテーブルの列名を指定してください。
    • 回答としてマーク クサキ 2010年1月21日 9:20
    2010年1月19日 9:10
    モデレータ
  • > (追加の質問ですが、Grid.TopLeftHeaderCell.Value の設定もデザイナーでできまっせんか?)

    スマートタグからの設定画面の下の方にある HeaderText で、各列のタイトルを設定できまっす。


    > > このことが関係してないでしょうか?
    >             for (int i = 0; i < 100; i++)
    >             {
    >                 dt.Rows[i][0] = 995 + i; dt.Rows[i][1] = 1995 + i;
    >             }
    > のようなコーディングで、数値型だと思いますが。

    そうではなさそうです。
    その for ループの後に次のコードを書いて実行すると、"String" と表示されると思います。
    MessageBox.Show(dt.Rows[0][0].GetType().Name);

    ひらぽんさんの例をそのままコーディングされている場合、
    dt.Columns.Add();
    というコードによって String 型の値を格納するための列が DataTable に追加されます。
    この場合、数値を代入しても、文字列として値が格納されます。
    数値のフォーマットを機能させるためには、DataTable への列の追加の際、次のような感じで適切な型を指定してください。
    (以下のように typeof(object) にすると、代入時の型のままで格納されます。)

    dt.Columns.Add("項目名", typeof(object)); // typeof(int) など。


    > > grid.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
    > しかし経験が浅いと、なななかHeaderCell.Style.Alignmentにはたどり着けませんでした。
    >  また、デザイナーでの指定は出来ないんですね?

    ですよね。私も最初は戸惑いました。
    1つ補足があります。上記は列ごとに指定する方法でした。
    通常は全列、同じ設定になることが多いと思いますが、その場合は以下のようにすることで一括指定できます。
    こちらの方法でしたら、デザイナの DataGridView 側のプロパティ(スマートタグじゃない方)で指定できます。

    grid.ColumnHeadersDefaultCellStyle.Alignment =
        DataGridViewContentAlignment.MiddleCenter;


    > > 3.
    > > 行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。
    >  grid.RowHeadersWidth = 10;
    >  grid.RowHeadersWidth = 500;
    >   などとしても、コンパイルは通りますが、まったく変わりませんでした。

    おかしいですね。
    書き忘れてましたが、grid.RowHeadersWidthSizeMode プロパティが Auto~ の場合は、grid.RowHeadersWidth の指定は無視されます。
    デフォルトは EnableResizing なので無視されることはないですが、Auto~ に変更されていないでしょうか?
    もしくは、追加されたコードの位置に問題があるのかもしれません。
    どちらもデザイナのプロパティで指定できますので、一度デザイナで指定してみてください。

    今思ったのですが、今回は選択が不要ということですので、もし行ヘッダー自体いらないということでしたら、grid.RowHeadersVisible で非表示にできます。これもデザイナでも指定可能です。

    • 回答としてマーク クサキ 2010年1月21日 9:21
    2010年1月20日 5:12
  • > ただ、ある程度小さくできるのですが、先に番号が消え、選択の右向きの▲とスペースが残り、
    > ある程度までしか小さく出来ませんでした。

    DataGridView の CellPainting イベントハンドラを以下のようにすると、期待された結果になるかもしれません。
    お試しいただければと思います。
    本当はもっと簡単にできればよいですが…。

    private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if (e.ColumnIndex == -1 && e.RowIndex != -1)
        {
            e.PaintBackground(e.ClipBounds, true);
            //e.Paint(e.ClipBounds,
            //    DataGridViewPaintParts.Background
            //    | DataGridViewPaintParts.ContentForeground);

            using (SolidBrush brush = new SolidBrush(e.CellStyle.ForeColor))
            using (StringFormat sf = new StringFormat())
            {
                sf.Alignment = StringAlignment.Far;
                sf.LineAlignment = StringAlignment.Center;
                sf.FormatFlags = StringFormatFlags.NoWrap;

                Rectangle rect = e.CellBounds;
                rect.Inflate(-5, 0);

                e.Graphics.DrawString((e.Value ?? "").ToString(), e.CellStyle.Font, brush, rect, sf);
            }
            e.Handled = true;
        }
    }

    • 編集済み TH01 2010年1月21日 4:19 念のため var を使わないように修正
    • 回答としてマーク クサキ 2010年1月21日 9:21
    2010年1月21日 4:13

すべての返信

  • 直接的な回答でなくて申しわけありませんが、DOBON さんのサイトに行けば色々使えそうな Tips があります。

    http://dobon.net/vb/dotnet/datagridview/index.html


    またどのくらいのデータを設定されるのか判りませんが、非バインド モードで

    > xxx.Rows.Add(row)

    は、パフォーマンスが非常に悪いので推奨できません。
    先に空の DataTable を作り、DataTable に値を設定してからバインド(もしくはその逆も可)する方が性能が高いです。

    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月15日 7:01
    モデレータ
  • ListViewが適しているかもしれませんね。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月15日 7:06
    モデレータ
  • > 先に空の DataTable を作り、DataTable に値を設定してからバインド(もしくはその逆も可)する方が性能が高いです。

    参考のため、空データのテーブルを作りバインドするサンプルです。

    private void button1_Click(object sender, EventArgs e)
    {
    	// 一万行の空データをグリッドに設定する
    	DataTable dt = new DataTable();
    	for (int i = 0; i < 5; i++)
    	{
    		dt.Columns.Add();
    	}
    	for (int i = 0; i < 10000; i++)
    	{
    		string[] values = 
    { string.Empty, string.Empty, string.Empty, string.Empty }; dt.Rows.Add(); } dataGridView1.DataSource = dt; }

    あとは

        DataRow(行インデックス)(列インデックス) = 値;

    みたいな感じで、DataTable の方を編集すればいいかと。

    #最近も某所で似たような質問があったな・・・
    • 編集済み ひらぽんModerator 2010年1月15日 7:25 途中で送信してしまいました
    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月15日 7:19
    モデレータ
  • ListView が今回の場合適しているようですが、乗りかかった船で、DataGridViewをも少し勉強したいと思います。

            // あとは
        // DataRow(行インデックス)(列インデックス) = 値;   
            // みたいな感じで、DataTable の方を編集すればいいかと。

    この部分のコーディングが具体的に分かりませんで、よろしくお願いします。
    今回の場合は配列をDataGridViewに表示するという流れで教えてもらえれば助かります。



    2010年1月18日 2:07
  • > この部分のコーディングが具体的に分かりませんで、よろしくお願いします。

    たとえばこんな感じになります。全ての行に同じデータを設定するとして・・・

    void method1(DataTable dt)
    {
            // 全ての行に設定
            foreach (DataRow row in dt.Rows)
           {
                row["customerId"] = 1;
                row["name"] = "ひらぽん";
                row["country"] = "Japan";
                row["city"] = "Tokyo"
           }
    }
    > 今回の場合は配列をDataGridViewに表示するという流れで教えてもらえれば助かります。

    配列がどういう形式か判りませんが、二次元配列の場合のサンプルです。
    ちなみにコーディングしただけなので試してません。悪しからず。<(_ _)>

    void method2(DataGridView grid, Array array)
    {
           DataTable dt = new DataTable();
           foreach (Object col in array[0])        {             dt.Columns.Add();        }

           foreach (Array values in array)
           {
                dt.Rows.Add(values);
           }
           grid.DataSource = dt;
    }
    • 回答としてマーク クサキ 2010年1月21日 9:18
    2010年1月18日 3:01
    モデレータ
  • 具体的に書いて頂き、DataSource、DataTable、DataRow の使い方も
    分かり基本的なことができるようになりました。ありがとうございました。

    もう少し質問させてください。

    1.数値の書式のためのFormatに関して
               
    xxx.DefaultCellStyle.Format = "d";
    xxx.Columns[0].DefaultCellStyle.Format = "d";
    xxx.Columns[0].DefaultCellStyle.Format = "N2";
    などのようにしますが、
    コンパイルは通りますが、実際には何もおこりません。(1000が1,000とならず1000まま)
    どうしたら機能するようになりますか?

    また、xxx.Columns[0].DefaultCellStyle. とコーディングした時点で、
    候補がポップアップしますが、Alignmentなどはありますが、Formatはありません。
    他のコントロールでも同様なことがありました(この時は機能はしていました)が、
    これは何か意図があるのでしょうか?


    2.ヘッダーでの Alignment の指定はどうするのでしょうか?


    3.選択そのものが出来ないようにするか、ヘッダーの幅を調整することは出来ないのでしょうか。
      という最初の質問ですが、コメントが付かないということは出来ないということでしょうか?
      (垂直と水平のスクロールバーの両方があると表は見難いと思いますが、水平のスクロールバー
       を無しにし狭い範囲に表示させたいことがあります。そのためにヘッダーのサイズを小さくしたい
       ということは良くあるような気がするのですが。)

    2010年1月19日 0:42
  • 全て答えている時間がないので、最初の質問だけ回答します。

    1.数値の書式のためのFormatに関して
               
    xxx.DefaultCellStyle.Format = "d";
    xxx.Columns[0].DefaultCellStyle.Format = "d";
    xxx.Columns[0].DefaultCellStyle.Format = "N2";
    などのようにしますが、
    コンパイルは通りますが、実際には何もおこりません。(1000が1,000とならず1000まま)
    どうしたら機能するようになりますか?

    基本的に、列の書式はデザイナで設定します。

    DataGridView コントロールの右上隅にあるスマート タグ グリフをクリック。
    列の編集ダイアログが開いたら設定したい列を選択。
    DefaultCellStyleの編集窓の右側ボタンをクリックして
    CellStyle ビルダ ダイアログを起動。Format を設定します。

    コーディングでやるなら、以下を参照してください。

    http://dobon.net/vb/dotnet/datagrid/columnformat.html

    他の質問に関しては、上記 DOBON さんのところで検索してみてください。

    • 回答としてマーク クサキ 2010年1月21日 9:19
    2010年1月19日 6:01
    モデレータ
  • 1.
    > コンパイルは通りますが、実際には何もおこりません。(1000が1,000とならず1000まま)
    > どうしたら機能するようになりますか?

    値の型が数値の場合はフォーマットされますが、
    値が文字列の "1000" の場合はフォーマットされません。
    grid[0, 0].Value = 1000;   // される
    grid[0, 0].Value = "1000"; // されない
    このことが関係してないでしょうか?

    > また、xxx.Columns[0].DefaultCellStyle. とコーディングした時点で、
    > 候補がポップアップしますが、Alignmentなどはありますが、Formatはありません。

    それはおかしいですね。
    もしかして、たとえば以下の状況に近い話ではないでしょうか?

    DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
    col.MaxInputLength = 100;
    grid.Columns.Add(col);
    grid.Columns[0]. // DataGridViewColumn 型なので MaxInputLength は選択肢にでない。

    > 2.ヘッダーでの Alignment の指定はどうするのでしょうか?

    ヘッダーに対する Alignment 指定でしたら、次のようにします。
    grid.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;

    > 3.選択そのものが出来ないようにするか、ヘッダーの幅を調整することは出来ないのでしょうか。

    行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。

    > 感想ですが、編集もしたくない、ソートもしたくない、選択もしたくない、
    > ただ、単に表を作るだけが難しいいんですね。

    複雑なコントロールなのでいろんなことができますが、確かに最初はとっつきにくいと思います。
    ご質問ではない点も含め、一応、以下にそれぞれについて書かせてもらいます。

    ■編集不可
    grid.ReadOnly = true;
    このほかに、列単位、行単位、セル単位、と、様々な制御ができます。
    CellBeginEdit イベントを使えば、プログラムで制御することもできます。

    ■ソート不可
    grid.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable;

    ■選択不可
    やはり、色の変更での対応がよいと思います。
    var style = grid.Columns[0].DefaultCellStyle;
    style.SelectionBackColor = SystemColors.Window;
    style.SelectionForeColor = SystemColors.WindowText;

    別の方法としては、データの表示処理の最後で
    grid.CurrentCell = null;
    を実行し、CurrentCellChanged イベントハンドラで
    private void grid_CurrentCellChanged(object sender, EventArgs e)
    {
        var grid = sender as DataGridView;
        if (grid == null) return;
        if (grid.CurrentCell != null)
            grid.BeginInvoke(new Action(() => { grid.CurrentCell = null; }));
    }
    とすることで、カレントセルがない状態(=選択セルがない状態)にできます。
    ただし、こうしたところで色変更に勝るメリットはなさそうですが。

    • 回答としてマーク クサキ 2010年1月21日 9:19
    2010年1月19日 7:09
  • 3.選択そのものが出来ないようにするか、ヘッダーの幅を調整することは出来ないのでしょうか。
      という最初の質問ですが、コメントが付かないということは出来ないということでしょうか?
    コントロールを選択不可にするには、以下のように ReadOnly プロパティが True の場合、
    マウス・キー関連のイベントを無効にし、さらにスタイルも変更し、
    タブキーでもフォーカスが設定できないようにします。
    ''' <summary>
    ''' 読み取り専用のプロパティを上書きする。
    ''' </summary>
    Public Shadows Property [ReadOnly]() As Boolean
        Get
            Return MyBase.ReadOnly
        End Get
        Set(ByVal value As Boolean)
            MyBase.ReadOnly = value
            Me.SetStyle(Windows.Forms.ControlStyles.Selectable, Not value)
        End Set
    End Property
    
    
    ''' <summary>
    ''' キー押下時のイベントハンドラ
    ''' </summary>
    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
        If (Me.ReadOnly) Then Return
        MyBase.OnKeyDown(e)
    End Sub
    
    ''' <summary>
    ''' キーアップ時のイベントハンドラ
    ''' </summary>
    Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs)
        If (Me.ReadOnly) Then Return
        MyBase.OnKeyUp(e)
    End Sub
    
    ''' <summary>
    ''' マウス押下時のイベントハンドラ
    ''' </summary>
    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        If (Me.ReadOnly) Then Return
        MyBase.OnMouseDown(e)
    End Sub
    
    ''' <summary>
    ''' マウスポインタがデザイナの境界内に入った時のイベントハンドラ
    ''' </summary>
    Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
        If (Me.ReadOnly) Then Return
        MyBase.OnMouseEnter(e)
    End Sub
    
    ''' <summary>
    ''' マウスポインタがコントロールを離れた時のイベントハンドラ
    ''' </summary>
    Protected Overrides Sub OnMouseLeave(ByVal eventargs As System.EventArgs)
        If (Me.ReadOnly) Then Return
        MyBase.OnMouseLeave(eventargs)
    End Sub
    
    ''' <summary>
    ''' マウスアップ時のイベントハンドラ
    ''' </summary>
    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
        If (Me.ReadOnly) Then Return
        MyBase.OnMouseUp(e)
    End Sub
    2010年1月19日 7:14
    モデレータ
  • あ、いけね。C# でしたね。
    上記 VB.NET のコードですが、C# に置き換えて実装ください。<(_ _)>

    #なんだかんだ言いつつ結局出てきてしまう・・・
    2010年1月19日 7:19
    モデレータ
  • > コーディングでやるなら、以下を参照してください。
    > http://dobon.net/vb/dotnet/datagrid/columnformat.html

    私のコーディングもDOBON さんの
    http://dobon.net/vb/dotnet/datagridview/format.html
    と同じようなコーディングですが、機能していません。


    ただ、基本的に、列の書式はデザイナで設定し他方が良いようですね。
    現在、全てコーディングで作っていますが、デザイナーで見ている限り、
    DataGridViewの灰色の矩形があるだけで、何のためのものかが一目で分かりません。
    デザイナー段階でヘッダーに文字を表示するために列はデザイナーでやることにします。
    また、この方が質問していたプロパティも簡単に変更できて良さそうですね。
    (やっと、プロパティのところに、列の追加とか列の編集があるのか分かりました)

    そこで、また疑問ですが、
    現在、コーディングだけの場合、DataTableと関係付けるために、
               DataTable dt = new DataTable();
               for (int i = 0; i < 2; i++)
                {
                    dt.Columns.Add();
                }
    のようなコーディングをしていますが、デザイナーで列を追加した場合は
    DataTableとの関連付けはどのようにしたら良いですか?

     

    2010年1月19日 8:22
  • デザイナーで列を追加した場合は
    DataTableとの関連付けはどのようにしたら良いですか?
    DataGridView の 「列の編集」 で設定したい列を選択、
    DataPropertyName にテーブルの列名を指定してください。
    • 回答としてマーク クサキ 2010年1月21日 9:20
    2010年1月19日 9:10
    モデレータ
  • > DataGridView の 「列の編集」 で設定したい列を選択、
    > DataPropertyName にテーブルの列名を指定してください。
    これでデザイナーで設定したものと、DataTableを関連付けることができました。
    (追加の質問ですが、Grid.TopLeftHeaderCell.Value の設定もデザイナーでできまっせんか?)


    1.それで、デザイナーでFormatの指定を、N2やcなどしましたが、
    機能せず、1000が1,000とならず1000ままです。

    > 値の型が数値の場合はフォーマットされますが、
    > 値が文字列の "1000" の場合はフォーマットされません。
    > grid[0, 0].Value = 1000;   // される
    > grid[0, 0].Value = "1000"; // されない
    > このことが関係してないでしょうか?
                for (int i = 0; i < 100; i++)
                {
                    dt.Rows[i][0] = 995 + i; dt.Rows[i][1] = 1995 + i;
                }
    のようなコーディングで、数値型だと思いますが。


    > 2.ヘッダーでの Alignment の指定はどうするのでしょうか?
    > ヘッダーに対する Alignment 指定でしたら、次のようにします。
    > grid.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
      上手くいきました。ありがとうございました。
     しかし経験が浅いと、なななかHeaderCell.Style.Alignmentにはたどり着けませんでした。
     また、デザイナーでの指定は出来ないんですね?


    > 3.
    > 行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。
     grid.RowHeadersWidth = 10;
     grid.RowHeadersWidth = 500;
      などとしても、コンパイルは通りますが、まったく変わりませんでした。

    ひらぽんさんが、イベント等を使いわざわざコーディングして頂きましたが、
    ヘッダーの幅を小さくしたいだけで、今回は何とか、そのままのサイズで
    行けますので、あれだけのコーディングにトライするのは躊躇します。

    2010年1月20日 2:20
  • 3.
    > 行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。
     grid.RowHeadersWidth = 10;
     grid.RowHeadersWidth = 500;
    などとしても、コンパイルは通りますが、まったく変わりませんでした。

    ひらぽんさんが、イベント等を使いわざわざコーディングして頂きましたが、
    ヘッダーの幅を小さくしたいだけで、今回は何とか、そのままのサイズで
    行けますので、あれだけのコーディングにトライするのは躊躇します。
    あれはマウスイベントやキーイベントを無効にして、グリッドを選択不可にするだけです。
    幅は関係ありません。
    2010年1月20日 4:02
    モデレータ
  • > (追加の質問ですが、Grid.TopLeftHeaderCell.Value の設定もデザイナーでできまっせんか?)

    スマートタグからの設定画面の下の方にある HeaderText で、各列のタイトルを設定できまっす。


    > > このことが関係してないでしょうか?
    >             for (int i = 0; i < 100; i++)
    >             {
    >                 dt.Rows[i][0] = 995 + i; dt.Rows[i][1] = 1995 + i;
    >             }
    > のようなコーディングで、数値型だと思いますが。

    そうではなさそうです。
    その for ループの後に次のコードを書いて実行すると、"String" と表示されると思います。
    MessageBox.Show(dt.Rows[0][0].GetType().Name);

    ひらぽんさんの例をそのままコーディングされている場合、
    dt.Columns.Add();
    というコードによって String 型の値を格納するための列が DataTable に追加されます。
    この場合、数値を代入しても、文字列として値が格納されます。
    数値のフォーマットを機能させるためには、DataTable への列の追加の際、次のような感じで適切な型を指定してください。
    (以下のように typeof(object) にすると、代入時の型のままで格納されます。)

    dt.Columns.Add("項目名", typeof(object)); // typeof(int) など。


    > > grid.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
    > しかし経験が浅いと、なななかHeaderCell.Style.Alignmentにはたどり着けませんでした。
    >  また、デザイナーでの指定は出来ないんですね?

    ですよね。私も最初は戸惑いました。
    1つ補足があります。上記は列ごとに指定する方法でした。
    通常は全列、同じ設定になることが多いと思いますが、その場合は以下のようにすることで一括指定できます。
    こちらの方法でしたら、デザイナの DataGridView 側のプロパティ(スマートタグじゃない方)で指定できます。

    grid.ColumnHeadersDefaultCellStyle.Alignment =
        DataGridViewContentAlignment.MiddleCenter;


    > > 3.
    > > 行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。
    >  grid.RowHeadersWidth = 10;
    >  grid.RowHeadersWidth = 500;
    >   などとしても、コンパイルは通りますが、まったく変わりませんでした。

    おかしいですね。
    書き忘れてましたが、grid.RowHeadersWidthSizeMode プロパティが Auto~ の場合は、grid.RowHeadersWidth の指定は無視されます。
    デフォルトは EnableResizing なので無視されることはないですが、Auto~ に変更されていないでしょうか?
    もしくは、追加されたコードの位置に問題があるのかもしれません。
    どちらもデザイナのプロパティで指定できますので、一度デザイナで指定してみてください。

    今思ったのですが、今回は選択が不要ということですので、もし行ヘッダー自体いらないということでしたら、grid.RowHeadersVisible で非表示にできます。これもデザイナでも指定可能です。

    • 回答としてマーク クサキ 2010年1月21日 9:21
    2010年1月20日 5:12
  • >> (Grid.TopLeftHeaderCell.Value の設定もデザイナーでできまっせんか?)
    > スマートタグからの設定画面の下の方にある HeaderText で、各列のタイトルを設定できまっす。
    各列のヘッダーは設定画面の下の方にある HeaderText で設定できますが、
    行ヘッターの一番上にある、TopLeftHeaderCell を変更するところは無いようですが?


    > dt.Columns.Add("項目名", typeof(object)); // typeof(int) など。

    dt.Columns.Add("Column1", typeof(double));
    dt.Columns.Add("Column2", typeof(int));
    のようにすることで、出来きるようになりました。

    しかし、以下のようにColumn2をdoubleにすると実行時に、下記のエラーになります。
    dt.Columns.Add("Column2", typeof(double));
    エラー:
    DataGridView で次の例外が発生しました。
    System.FormatException: 形式指定子が無効です。
    場所 System.Number.FormatDouble(Double value, String format, NumberFormatInfo info )
    ・・・
    ・・・

    Column1とColumn2は同じ状態だと思うのですが、なぜでしょうか?(また、大問題が発生しました)


    > 通常は全列、同じ設定になることが多いと思いますが、その場合は以下のようにすることで一括指定できます。
    > こちらの方法でしたら、デザイナの DataGridView 側のプロパティ(スマートタグじゃない方)で指定できます。
    > grid.ColumnHeadersDefaultCellStyle.Alignment =
    >    DataGridViewContentAlignment.MiddleCenter;
    こちらでも上手くいきました。


    >> > 3.
    >> > 行ヘッダーの幅は、grid.RowHeadersWidth で指定できます。
    >>  grid.RowHeadersWidth = 10;
    >>  などとしても、コンパイルは通りますが、まったく変わりませんでした。
    > 書き忘れてましたが、grid.RowHeadersWidthSizeMode プロパティが Auto~ の場合は、
    > grid.RowHeadersWidth の指定は無視されます。
    > デフォルトは EnableResizing なので無視されることはないですが、Auto~ に変更されていないでしょうか?
    EnableResizingやDisableResizingですがダメです。

    > もしくは、追加されたコードの位置に問題があるのかもしれません。
    grid.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders);
    の後に置くと機能しだしました。
    ただ、ある程度小さくできるのですが、先に番号が消え、選択の右向きの▲とスペースが残り、
    ある程度までしか小さく出来ませんでした。

    AutoResizeRowHeadersWidthはこれまで、行ヘッダーの2桁以上の表記が上手くできないため入れていました。
    現在はデザイナで色々触った結果か、無くても表記がおかしくならないので、AutoResizeRowHeadersWidthを
    カットすることが出来、その結果、grid.RowHeadersWidth もどこにでもおけるようになりました。

    > 今思ったのですが、今回は選択が不要ということですので、もし行ヘッダー自体いらないということでしたら、
    > grid.RowHeadersVisible で非表示にできます。
    選択が不要でも、行ヘッダーに表示する番号は是非欲しいです。

    2010年1月21日 1:28
  • > しかし、以下のようにColumn2をdoubleにすると実行時に、下記のエラーになります。
    > dt.Columns.Add("Column2", typeof(double));
    > エラー:
    > DataGridView で次の例外が発生しました。
    > System.FormatException: 形式指定子が無効です。
    > 場所 System.Number.FormatDouble(Double value, String format, NumberFormatInfo info )
    > ・・・
    は私のミスです。
    デザイナーを触りだしている間に、コーディングの方を忘れていまして、
    コーディング方は以下のようで、
    cDataGridView.Columns[0].DefaultCellStyle.Format = "N2";
    cDataGridView.Columns[1].DefaultCellStyle.Format = "d";
    doubleの時に"d"し、上記のエラーになりました。




    2010年1月21日 1:57
  • > 行ヘッターの一番上にある、TopLeftHeaderCell を変更するところは無いようですが?

    大変失礼しました。勘違いしていました。
    TopLeftHeaderCell.Cell をデザイナで指定することはできないようです。

    2010年1月21日 3:01
  • > ただ、ある程度小さくできるのですが、先に番号が消え、選択の右向きの▲とスペースが残り、
    > ある程度までしか小さく出来ませんでした。

    DataGridView の CellPainting イベントハンドラを以下のようにすると、期待された結果になるかもしれません。
    お試しいただければと思います。
    本当はもっと簡単にできればよいですが…。

    private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if (e.ColumnIndex == -1 && e.RowIndex != -1)
        {
            e.PaintBackground(e.ClipBounds, true);
            //e.Paint(e.ClipBounds,
            //    DataGridViewPaintParts.Background
            //    | DataGridViewPaintParts.ContentForeground);

            using (SolidBrush brush = new SolidBrush(e.CellStyle.ForeColor))
            using (StringFormat sf = new StringFormat())
            {
                sf.Alignment = StringAlignment.Far;
                sf.LineAlignment = StringAlignment.Center;
                sf.FormatFlags = StringFormatFlags.NoWrap;

                Rectangle rect = e.CellBounds;
                rect.Inflate(-5, 0);

                e.Graphics.DrawString((e.Value ?? "").ToString(), e.CellStyle.Font, brush, rect, sf);
            }
            e.Handled = true;
        }
    }

    • 編集済み TH01 2010年1月21日 4:19 念のため var を使わないように修正
    • 回答としてマーク クサキ 2010年1月21日 9:21
    2010年1月21日 4:13
  • dataGridView1_CellPaintingイベントでご指示のコーディグを入れると、
    選択の右向きの▲とスペースが消え、サイズも小さくできるようになりました。
    (コメントアウトしているものは、文字が重なりダメでした)

    色んな勉強や体験ができ今回の範囲のDataGridViewCellは自身を持ってできるようになりました。
    皆さん、沢山の助言ありがとうございました。

    2010年1月21日 9:17