DataGridViewのDataSourceを指定した後列名を自由自在に変更する方法

C#でDBからデータDataTableとして取得し、DataGridViewに表示する際、DataSourceをに取得したデータを指定する方法ってよく使いますよね!

ただそのようにしてしまうと列の名前がDataTableの列名に引っ張られてしまいます。。。

なので後から変更しようとすると、結構めんどくさい。。

今回はそんなめんどくさいを解決する方法を解説していきます!

目次

まず通常の方法でDataSourceにDataTableを指定してみる。

以下のような形でフォームを作ります。

シンプルにフォームにDataGridViewを置いただけです。

中身のコードはこんな感じです。

using System;
using System.Data;
using System.Windows.Forms;

namespace DataSourceBlog { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.DataSource = GetDataTable();
    }

    public DataTable GetDataTable()
    {
        var dt = new DataTable();
        dt.Columns.Add("UserId");
        dt.Columns.Add("UserName");
        dt.Columns.Add("age");

        dt.Rows.Add(new object[]{1,"Alex",19});
        dt.Rows.Add(new object[] { 2, "John", 15 });
        dt.Rows.Add(new object[] { 3, "Nick", 25 });

        return dt;
    }
}

}

これを実行すると下記のようになります。

列名はDataTableの列名になっています。

この列名を変更するには通常なら下記のようにします。、

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = GetDataTable();
            dataGridView1.Columns["UserId"].HeaderText = "ユーザーID";
            dataGridView1.Columns["UserName"].HeaderText = "ユーザー名";
            dataGridView1.Columns["age"].HeaderText = "年齢";
        }

ですがこの方法以外に、もっとシンプルに列名を指定しつつデータを表示する方法があります。

シンプルに列名を変更する方法

💡 DataSource を後から差し替えるときに列名変更がリセットされて困ったら C# DataGridView の DataSource を後から変更する全パターン も合わせて読むと整理が早いです。

先に行っておくと、この方法はDataSourceにDatatableを指定する方法ではございません。

むしろDataSourceにDatatableを指定してしまうと、この方法は使えません。

DataSourceにはオブジェクトのリストを渡します。

なのでDataSourceに表示する用のクラスを作ります。

namespace DataSourceBlog
{
    public class DataItems
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public int Age { get; set; }

    public DataItems(int userId,string userName,int age)
    {
        UserId = userId;
        UserName = userName;
        Age = age;
    }
}

}

次にDataTableを引数に上記クラスのリストを返してくれるメソッドを作成します。

        private List<DataItems> GetItems(DataTable table)
        {
            var result = new List<DataItems>();

        foreach (DataRow row in table.Rows)
        {
            result.Add(new DataItems(Convert.ToInt16(row[&quot;UserId&quot;]),row[&quot;UserName&quot;].ToString(),Convert.ToInt16(row[&quot;age&quot;])));
        }

        return result;

    }</code></pre></div>

最後にこのクラスのリストを表示させます。

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.DataSource = GetItems(GetDataTable());
    }

実行するとこんな感じ。

このままでは列名は指定できていません。

ということで、シンプルな方法で列名を指定していきます。

以下のような形でDisplayNameを指定してください。

これだけで表示できます。

using System.ComponentModel;

namespace DataSourceBlog { public class DataItems { [DisplayName("ユーザーID")] public int UserId { get; set; }

    [DisplayName(&quot;ユーザー名&quot;)]
    public string UserName { get; set; }

    [DisplayName(&quot;年齢&quot;)]
    public int Age { get; set; }

    public DataItems(int userId,string userName,int age)
    {
        UserId = userId;
        UserName = userName;
        Age = age;
    }
}

}

これで実行すると下記のようになります。

いちいち表示するためのクラスをつくるのがだるい??

今回の方法では、一度DataTableを作成し、それを表示するためのクラスに渡すという方法をとりました。

正直この方法は冗長だと思います。

実際の業務で使うとすれば、一度DBからDataTableを取得しそれをクラスに変換するわけですから、メモリにも悪いし、メンテンナンス性も悪いです。

なので、このようなパターンを使う場合は、SqlDataReaderを使って処理をぶん回すことをお勧めします。

要するにDBからデータを取得する際、一度DataTableにせずそのまま表示用のクラスを作ってしまうという方法です。

そのようにしてしまえば、DBから効率よくデータを取得し列名もわかりやすく変更し、ストレスなくデータの表示ができるのではないでしょうか!

以上!

💡 補足: 業務系の現場でよくハマるパターン

俺もこの DataGridView の列名カスタマイズで何度も詰みました。3つ覚えとくと事故が減ります。

① 列名変更が DataSource 差し替えでリセットされる

dgv.Columns["id"].HeaderText = "ID番号" で変更しても、 dgv.DataSource = newTable で再バインドすると消えます。回避は AutoGenerateColumns = false にして、列を全部手動定義しておく型。 DataSource 差し替えの全パターン でも解説してます。

② HeaderText と Name の使い分けで混乱

HeaderText は画面表示用、Name はコードからアクセスするキー。これを混同して dgv.Columns["顧客ID"] としても見つからない(Name は「id」のまま)。Name は英数字で固定、HeaderText を画面用に変える、が業務系の鉄則。

③ DisplayIndex を設定しないと列順が想定と違う

DataTable のカラム順 = DataGridView の表示順、になるけど、コードで列を追加すると末尾に行きます。順序を制御したければ DisplayIndex を明示的に設定する。これ知らないと「コード書いたら列が右に飛んだ」と混乱します。

❓ よくある質問

Q1. 列ヘッダーを日本語にするには?

A. dgv.Columns["id"].HeaderText = "ID" で個別に設定するか、デザイナで列を手動定義して HeaderText を日本語で書きます。AutoGenerateColumns = true のまま使うと再バインドでリセットされるので false にするのがセオリー。

Q2. 列の表示順を固定したい

A. dgv.Columns[N].DisplayIndex = M で設定。または列を手動定義して dgv.Columns.Add する順番で並べる。 DataGridView × DataTable で全体の流れを書いてます。

Q3. 特定の列を非表示にする

A. dgv.Columns["id"].Visible = false でOK。ID列は内部キーとして持っておきたいけど画面には出したくない、というケースで頻出。

Q4. DataSource を差し替えても列定義を維持するには?

A. AutoGenerateColumns = false に固定 → 列を最初に1回だけ手動定義 → DataSource 変更時は列定義はそのまま。新しい DataTable のカラム名が DataPropertyName と一致してれば値だけ差し替わります。詳しくは DataSource 差し替え全パターン で書いてます。

Q5. 動的に列を追加したい

A. new DataGridViewTextBoxColumn { Name = "col", HeaderText = "ヘッダー", DataPropertyName = "col" } を作って dgv.Columns.Add(...) で追加。DataPropertyName を DataTable の列名と一致させればバインディングが効きます。 DataTable × Linq の3パターン で動的にカラムを生成する Linq パターンも参照。

📚 関連記事

この記事が気に入ったら
いいねしてね!

どんどんシェア待ってるぜ!!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次