トップC# > DataGridView

DataGridView

1.DataGridViewの基本

DataGridViewクラスのインスタンスを生成し、列名とデータを表示するプログラムを下に示す。

using System;
using System.Windows.Forms;

class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new DataGrid());
    }
}

class DataGrid : Form {
    string[] heads  = { "a", "b", "c" };
    string[][] data = { new string[] {"1", "2", "3"}, new string[] {"11", "12", "13"} };

    public DataGrid() {
        Text = "DataGridView Test";
        DataGridView dataGridView  = new DataGridView() { Dock = DockStyle.Fill };
        dataGridView.ColumnCount = heads.Length;
        for (int i = 0; i < heads.Length; i++)
            dataGridView.Columns[i].Name = heads[i];
        for (int j = 0; j < data.Length; j++)
            dataGridView.Rows.Add(data[j]);
        this.Controls.Add(dataGridView);
    }
}

2.行番号を表示する

行番号を表示する方法は色々ある。 その中で比較的にシンプルなのが DataGridViewRowPostPaint イベントを使う方法である。 プログラムを下に示す。

using System;
using System.Drawing;
using System.Windows.Forms;

class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new DataGrid());
    }
}

class DataGrid : Form {
    string[] heads  = { "a", "b", "c" };
    string[][] data = { new string[] {"1", "2", "3"}, new string[] {"11", "12", "13"} };

    public DataGrid() {
        Text = "DataGridView Test";
        DataGridView dataGridView  = new DataGridView() { Dock = DockStyle.Fill };
        dataGridView.RowPostPaint += new DataGridViewRowPostPaintEventHandler(rowPostPaint);
        dataGridView.ColumnCount = heads.Length;
        for (int i = 0; i < heads.Length; i++)
            dataGridView.Columns[i].Name = heads[i];
        for (int j = 0; j < data.Length; j++)
            dataGridView.Rows.Add(data[j]);
        this.Controls.Add(dataGridView);
    }

    // 行番号を表示する
    private void rowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) {
        Rectangle rect = e.RowBounds;
        rect.Width = ((DataGridView)sender).RowHeadersWidth - 4;
        TextRenderer.DrawText(e.Graphics, (e.RowIndex+1).ToString(),
                e.InheritedRowStyle.Font, rect, e.InheritedRowStyle.ForeColor,
                TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
    }
}

DataGridViewCellPaintingイベントを使って行番号を表示するには、次のようにする。

    dataGridView.CellPainting += new DataGridViewCellPaintingEventHandler(cellPainting);

    private void cellPainting(object sender, DataGridViewCellPaintingEventArgs e) {
        if (e.ColumnIndex < 0 && e.RowIndex >= 0) {
            e.Paint(e.ClipBounds, DataGridViewPaintParts.All);
            Rectangle indexRect = e.CellBounds;
            indexRect.Inflate(-2, -2);
            TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(),
                e.CellStyle.Font, indexRect, e.CellStyle.ForeColor,
                TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
            e.Handled = true; // 描画が完了したことを知らせる
        }
    }

3.表示レイアウト

次のプログラムでは、列名の表示を中央揃え、データセルの表示を右揃えに変更している。 デフォルトは左揃えである。

// datagrid.cs  2013.10.31 by Minoru Hatada

using System;
using System.Drawing;
using System.Windows.Forms;

class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new DataGrid());
    }
}

class DataGrid : Form {
    string[] heads  = { "a", "b", "c" };
    string[][] data = { new string[] {"1", "2", "3"}, new string[] {"11", "12", "13"} };

    public DataGrid() {
        Text = "DataGridView Test";
        DataGridView dataGridView  = new DataGridView() { Dock = DockStyle.Fill };
        dataGridView.RowPostPaint += new DataGridViewRowPostPaintEventHandler(rowPostPaint);
        dataGridView.ColumnHeadersDefaultCellStyle.Alignment = 
            DataGridViewContentAlignment.MiddleCenter; // 列名を中央揃えに
        dataGridView.ColumnCount = heads.Length;
        for (int i = 0; i < heads.Length; i++) {
            dataGridView.Columns[i].Name = heads[i];
            dataGridView.Columns[i].DefaultCellStyle.Alignment = 
                                DataGridViewContentAlignment.MiddleRight;
        }
        for (int j = 0; j < data.Length; j++)
            dataGridView.Rows.Add(data[j]);
        this.Controls.Add(dataGridView);
    }

    // 行番号を表示する
    private void rowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) {
        Rectangle rect = e.RowBounds;
        rect.Width = ((DataGridView)sender).RowHeadersWidth - 4;
        TextRenderer.DrawText(e.Graphics, (e.RowIndex+1).ToString(),
                e.InheritedRowStyle.Font, rect, e.InheritedRowStyle.ForeColor,
                TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
    }
}

4.行の追加・削除

末尾に行を追加するときはdataGridView.Rows.Add() メソッドを使用する。

特定の位置 rowIndex に行を追加するときはdataGridView.Rows.Insert(rowIndex, dataGridViewRow) メソッドを使用する。

全ての行を削除するには dataGridView.Rows.Clear() メソッドを使用する。

特定の行 rowToDelete を削除するには dataGridView.Rows.RemoveAt(rowToDelete); とする。

5.DataGridの一番下の新しい行(*行)が表示されないようにする

dataGrid.AllowUserToAddRows を false に設定すると、 DataGridの一番下に表示される新しい行(*行)が表示されなくなる。 ただし、この状態では、表示された行のセルの編集は可能である。 dataGrid.ReadOnlyプロパティを true とすると、セルの編集も出来なくなる。

なお、dataGrid.ReadOnlyプロパティを true としただけの場合は、入力はできないが、 一番下に空行が表示される。このような使い方は一般的にはないであろう。

6.行、列を非表示にする

RowHeadersVisibleプロパティに false を設定すると、行ヘッダは表示されなくなる。

指定した列や行を非表示にするには、列(DataGridViewColumnオブジェクト)や 行(DataGridViewRowオブジェクト)のVisibleプロパティをfalseにする。 例えば dataGridView.Columns[3].Visible = false のようにする。

7.指定した行や列を固定してスクロールされないようにする

例えば、

  dataGridView.Columns[1].Frozen = true;
とすると、dataGridViewの左の2列が固定され、スクロールされなくなる。 同様に、
  dataGridView.Rows[0].Frozen = true;
とすると、dataGridViewの一番上の行が固定され、スクロールされなくなる。

次のプログラムで行が固定されていることを確認した。

using System;
using System.Windows.Forms;

class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new DataGrid());
    }
}

class DataGrid : Form {
    string[] heads  = { "品名", "数量", "単価", "売上高" };
    string[][] data = { new string[] {"abcd", "1", "200", "200"}, 
                        new string[] {"何か", "10", "500", "5000"}, 
                        new string[] {"あれ", "5", "200", "1000"}, 
                        new string[] {"これ", "10", "400", "4000"}, 
    };

    public DataGrid() {
        Text = "DataGridView Test";
        DataGridView dataGridView  = new DataGridView() { 
            Dock = DockStyle.Fill, 
            AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells,
        };
        dataGridView.ColumnCount = heads.Length;
        for (int i = 0; i < heads.Length; i++) {
            dataGridView.Columns[i].Name = heads[i];
            dataGridView.Columns[i].DefaultCellStyle.Alignment 
                = DataGridViewContentAlignment.MiddleRight;
            dataGridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
        }
        for (int j = 0; j < data.Length; j++) {
            dataGridView.Rows.Add(data[j]);
        }
        dataGridView.Rows[0].Frozen = true;     // 先頭行を固定する

        this.Controls.Add(dataGridView);
    }
}

下の画面はスクロールによって2行目が隠れた状態である。1行目は固定されている。

この画面から分かるように、列名と境界線の間に少し余白がある。この余白を縮小する方法があるか調べたが、 簡単ではないことが分かった。カスタムドローのような方法しかないようだ。 DataGridViewAutoSizeColumnsMode.AllCells は使えないので、そこまで手数をかけて変更するほどのものでもないだろう。

8.行の高さ

8.1 行の高さを設定する

全ての行の高さを例えば18ピクセルに変更するには、データをセットする前に dataGridView.RowTemplate.Height = 18 を実行する。

列ヘッダの高さを 50 ピクセルに設定するには dataGridView.ColumnHeadersHeight = 50 とする。

8.2 行の高さや列の幅をユーザが変更できないようにする

デフォルトでは行の高さや列の幅はマウス操作で変更できる(境界線をドラッグする)。

dataGridView.AllowUserToResizeColumns = false;	// dataGridViewの列の幅をユーザーが変更できないようにする
dataGridView.AllowUserToResizeRows = false; 	// dataGridViewの行の高さをユーザーが変更できないようにする

特定の列 m、行 n に対しては dataGridView.Columns[m].AllowUserToResizeColumns、 dataGridView.Rows[n].AllowUserToResizeColumns を false にする。

9.セルの余白を設定する

セルの余白を好みの値に設定するには dataGridView.RowTemplate.DefaultCellStyle.Padding プロパティに余白(「左」「上」「右」「下」)を設定する。 このとき、余白に応じてセルの高さを修正する必要がある。 下に、プログラム例と実行画面を示す。

// dgv01.cs
using System;
using System.Windows.Forms;

class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new DataGrid());
    }
}

class DataGrid : Form {
    string[] heads  = { "a", "b", "c" };
    string[][] data = { new string[] {"1", "2", "3"}, new string[] {"11", "12", "13"} };

    public DataGrid() {
        Text = "DataGridView Test";
        DataGridView dataGridView  = new DataGridView() { Dock = DockStyle.Fill };
        dataGridView.RowTemplate.DefaultCellStyle.Padding = new Padding(5,5,5,7);
        dataGridView.RowTemplate.Height += 7;
        dataGridView.ColumnCount = heads.Length;
        for (int i = 0; i < heads.Length; i++)
            dataGridView.Columns[i].Name = heads[i];
        for (int j = 0; j < data.Length; j++)
            dataGridView.Rows.Add(data[j]);
        this.Controls.Add(dataGridView);
    }
}

余白をゼロにすると、下のように、スリムな表にできる。

プログラムを下に示す。列名の後ろのソートのマークを消すために、 列の SortMode を DataGridViewColumnSortMode.NotSortable としている。

左端の行ヘッダを消すために dataGridView.RowHeadersVisible = false としている。

// dgv1.cs
using System;
using System.Windows.Forms;

class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new DataGrid());
    }
}

class DataGrid : Form {
    string[] heads  = { "列1", "列2", "列3" };
    string[][] data = { 
        new string[] {"1111", "2222", "3333"}, 
        new string[] {"4444", "5555", "6666"} 
    };

    public DataGrid() {
        Text = "DataGridView Test";
        DataGridView dataGridView = new DataGridView() { Dock = DockStyle.Fill };
        dataGridView.RowHeadersVisible = false;
        dataGridView.AllowUserToAddRows = false;
        dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
        dataGridView.ColumnHeadersDefaultCellStyle.Padding = new Padding(0);
        dataGridView.RowTemplate.DefaultCellStyle.Padding = new Padding(0);
        dataGridView.ColumnHeadersHeight = 20;
        dataGridView.RowTemplate.Height -= 6;
        dataGridView.ColumnCount = heads.Length;
        for (int i = 0; i < heads.Length; i++) {
            dataGridView.Columns[i].Name = heads[i];
            dataGridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
        }
        for (int j = 0; j < data.Length; j++) {
            dataGridView.Rows.Add(data[j]);
        }
        this.Controls.Add(dataGridView);
    }
}

Marginプロパティにゼロを設定しても、デフォルトで僅かな余白が加えられる。 特に、列名(ColumnHeaders)に大き目の余白が加えられるようである。 これらの余白も無くすには、次のプログラムに示すように、 DataGridViewCellPaintingEventHandlerを使って自分で描画すればよい。 セルの幅や高さや文字列の配置は予め設定しておく。 (通常は、手間をかけてここまでこだわる必要はないだろうが)

    dataGridView.CellPainting += new DataGridViewCellPaintingEventHandler(cellPainting);

    void cellPainting(object sender, DataGridViewCellPaintingEventArgs e) {
	e.PaintBackground(e.ClipBounds, true);
	string text = Convert.ToString(e.FormattedValue);
        Color color = text.StartsWith("-") ? Color.Red : Color.Black;
    	TextRenderer.DrawText(e.Graphics, text, e.CellStyle.Font, e.CellBounds, color,
				 TextFormatFlags.HorizontalCenter);
	e.Handled = true;
    }

10.セルにツールチップを付ける

多数のセルにツールチップを付けるにはCellToolTipTextNeededイベントを使用する方がよさそう。 特定のセルにツールチップを付けるにはDataGridViewColumn.ToolTipTextプロパティの方が簡単である。 列ヘッダに対しては dataGridView.Columns[nCol].ToolTipText、行ヘッダでは dataGridView.Rows[nRow].HeaderCell.ToolTipText、データセルでは dataGridView[nCol,nRow].ToolTipText に文字列をセットする。

11.起動時にセルが選択されないようにする

DataGridViewコントロールでは、アプリケーションの実行開始時にデフォルトで左上隅(1行1列目) のセルが自動的に選択され、反転状態となる。 起動時にセルが選択されないようにするには、CurrentCellプロパティに null をセットすればよい。

ただし、DataGridViewが表示されてから CurrentCellプロパティに null をセットする必要があるため、 例えば、次のようにする。

public class MyForm : Form {

   DataGridView dataGridView;

  // フォームのコンストラクタ
   public MyForm() {
     dataGridView = new DataGridView() { Dock = DockStyle.Fill };
     this.Controls.Add(dataGridView);

     this.Shown += (s,e) => { dataGridView.CurrentCell = null; };
   }

}

この場合には、マウスでセルをクリックしたときは、セルが反転状態となる。 コンストラクタで、次のようにすれば、セルの選択ができなくなるため、セルをクリックしても反転表示は起きない。

    CurrentCell = null; 
    SelectionChanged += (s,e) => { CurrentCell = null; };

12.セルを選択する

起動時にセルを nCol列、nRow行 に設定するには、次のようにする。

    dataGridView.FirstDisplayedCell = dataGridView[nCol,nRow];

カレントセルを nCol列、nRow行 に設定するには、次のようにする。

    dataGridView.CurrentCell = dataGridView[nCol,nRow];

セルの値は Valueプロパティ(Object型)で取得・設定する。

デフォルトではセルをクリックすると個々のセルが選択される。 クリックしたセルを含む行全体が選択されるようにするには、次のようにする。

    dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

13.セルや行・列に文字色や背景色を設定する

背景色などは Styleプロパティに含まれる。 例えば、背景色の設定は次のようにする。

    dataGridView[nCol,nRow].Style.BackColor = Color.Aquamarine;

行全体、列全体の背景色を設定するには、次のようにする。

    dataGridView.Rows[nRow].DefaultCellStyle.BackColor = Color.Aquamarine;
    dataGridView.Columns[nCol].DefaultCellStyle.BackColor = Color.Aquamarine;

文字色を設定するときは、BackColor を ForeColor に変更する。

14.指定の行を画面の先頭に表示する

行nRowが画面に表示されていないとき、画面の先頭に表示するようにスクロールするには、 次のようにする。

    if (!dataGridView.Rows[nRow].Displayed) 
        dataGridView.FirstDisplayedScrollingRowIndex = nRow;