注意:ここで紹介しているDataGridは、System.Windows.Forms名前空間のDataGrid(Windowsフォーム)です。System.Web.UI.WebControls名前空間のDataGrid(Webフォーム)ではありません。
DataGridの列の幅を、その列にあるすべてのセルとヘッダの文字列の最大幅となるように自動調節するには、DataGridの列のすべてのセルの文字列(及びヘッダのHeaderText)の長さをGraphics.MeasureStringメソッドで調べ、一番長いものに列のWidthを設定するという方法になるでしょう。
この方法を使った簡単なコードを以下に紹介します。ここでは、DataGridのDataSourceにDataTableが設定されているものとします。
''' <summary> ''' DataGridの列の幅をTextの幅に合わせて変更する ''' </summary> ''' <param name="grid">対象とするDataGrid</param> ''' <param name="column">列の番号</param> Public Shared Sub AutoSizeColumnWidth( _ ByVal grid As DataGrid, ByVal column As Integer) 'DataGridのGraphicsを取得 Dim g As Graphics = Graphics.FromHwnd(grid.Handle) 'すべてのセルを調べて、一番広い幅を取得 Dim sf As New StringFormat(StringFormat.GenericTypographic) Dim dt As DataTable = CType(grid.DataSource, DataTable) Dim rowsCount As Integer = dt.Rows.Count Dim maxWidth As Single = 0 Dim i As Integer For i = 0 To rowsCount - 1 Dim [text] As String = grid(i, column).ToString() maxWidth = Math.Max(g.MeasureString( _ [text], grid.Font, grid.Width, sf).Width, maxWidth) Next i 'ヘッダの幅も考慮 Dim cs As DataGridColumnStyle = _ grid.TableStyles(dt.TableName).GridColumnStyles(column) maxWidth = Math.Max(g.MeasureString( _ cs.HeaderText, grid.Font, grid.Width, sf).Width, maxWidth) '破棄 g.Dispose() '幅の変更 cs.Width = CInt(maxWidth) + 8 End Sub
/// <summary> /// DataGridの列の幅をTextの幅に合わせて変更する /// </summary> /// <param name="grid">対象とするDataGrid</param> /// <param name="column">列の番号</param> public static void AutoSizeColumnWidth(DataGrid grid, int column) { //DataGridのGraphicsを取得 Graphics g = Graphics.FromHwnd(grid.Handle); //すべてのセルを調べて、一番広い幅を取得 StringFormat sf = new StringFormat(StringFormat.GenericTypographic); DataTable dt = ((DataTable) grid.DataSource); int rowsCount = dt.Rows.Count; float maxWidth = 0; for (int i = 0; i < rowsCount; i++) { string text = grid[i, column].ToString(); maxWidth = Math.Max(g.MeasureString( text, grid.Font, grid.Width, sf).Width, maxWidth); } //ヘッダの幅も考慮 DataGridColumnStyle cs = grid.TableStyles[dt.TableName].GridColumnStyles[column]; maxWidth = Math.Max(g.MeasureString( cs.HeaderText, grid.Font, grid.Width, sf).Width, maxWidth); //破棄 g.Dispose(); //幅の変更 cs.Width = (int) maxWidth + 8; }
この方法は「Windows Forms FAQ - 5.52 How can I autosize a column in my datagrid?」や「microsoft.public.dotnet.languages.vb - Re: how-to autosize the width of a column in a DataGrid」でも紹介されていますので、参考にしてください。
しかしこの方法には欠点があります。それは、セル内に表示される文字列をToStringで取得している点です。実際に表示される文字列はToStringで取得できる文字列と同じになるとは限りません。しかし残念ながら、実際に表示される文字列を取得するのはとても難しいです。例えばDataGridTextBoxColumnが設定されている場合は、DataGridTextBoxColumnのGetTextメソッドで取得できますが、このメソッドがprivateのため、通常はアクセスできません。
よって実際に表示される文字列を取得するには、「隠蔽されている非パブリックメンバを呼び出す」のようにリフレクションを使ってGetTextメソッドにアクセスするか、自分で列スタイルを作成するかなどの方法になりそうです。(自分でGetTextと同じことをするコードを書く方法もありますが、全く同じになる保障はありません。)
(この記事は、「.NETプログラミング研究 第50号」で紹介したものを基にしています。)