This article was contributed by
Tom Archer.
Environment: .NET, C#
Demo application to test datagrid resizing method
Introduction
One peculiar omission from the Windows Forms teams regarding the DataGrid
object is a method that enables you to resize the grid’s columns to visually accomodate the width of its widest data value. This method gives you that ability.
Acknowledgements
While searching for a solution to this problem, a friend emailed me some Visual Basic.NET code to accomplish the feat. While I could not get the code to compile (I’m assuming it was written during one of the .NET betas), I did re-write it in C# and got it to work. I’ll update this article to give a proper acknowledgment once I track down the original author’s name. However, I did want to make clear that some kind soul did get me 90% of the way there with their VB code and I finished the rest for my C# environment.
Using the Code
Syntax
Calling this method is very straightforward. It takes only two parameters:
public void SizeColumnsToContent(DataGrid dataGrid, int nRowsToScan)
- dataGrid—The DataGrid object to be resized
- nRowsToScan—The number of rows to scan when searching for the widest value for a given column. Passing a value of -1 indicates that all rows should be scanned.
Notes
- In my own code, I have defined a method as a member of my own
System.Windows.Forms.DataGrid
-derived class (DataGridEx
). I removed it from that class for this article to keep things simple. To use the method in the same manner that I did, simply remove the dataGrid parameter from the parameter list and replace the references todataGrid
with reference to thethis
object. - The reason for the
nRowsToScan
parameter is for performance issues regarding very large amounts of data. If you happen to have a datagrid with a large number of rows, you can simply have the grid’s columns sized according to the widest column of the first n rows instead of the method iterating through the entire data set for each column.
SizeColumnsToContent Method
public void SizeColumnsToContent(DataGrid dataGrid, int nRowsToScan) { // Create graphics object for measuring widths. Graphics Graphics = dataGrid.CreateGraphics(); // Define new table style. DataGridTableStyle tableStyle = new DataGridTableStyle(); try { DataTable dataTable = (DataTable)dataGrid.DataSource; if (-1 == nRowsToScan) { nRowsToScan = dataTable.Rows.Count; } else { // Can only scan rows if they exist. nRowsToScan = System.Math.Min(nRowsToScan, dataTable.Rows.Count); } // Clear any existing table styles. dataGrid.TableStyles.Clear(); // Use mapping name that is defined in the data source. tableStyle.MappingName = dataTable.TableName; // Now create the column styles within the table style. DataGridTextBoxColumn columnStyle; int iWidth; for (int iCurrCol = 0; iCurrCol < dataTable.Columns.Count; iCurrCol++) { DataColumn dataColumn = dataTable.Columns[iCurrCol]; columnStyle = new DataGridTextBoxColumn(); columnStyle.TextBox.Enabled = true; columnStyle.HeaderText = dataColumn.ColumnName; columnStyle.MappingName = dataColumn.ColumnName; // Set width to header text width. iWidth = (int)(Graphics.MeasureString (columnStyle.HeaderText, dataGrid.Font).Width); // Change width, if data width is // wider than header text width. // Check the width of the data in the first X rows. DataRow dataRow; for (int iRow = 0; iRow < nRowsToScan; iRow++) { dataRow = dataTable.Rows[iRow]; if (null != dataRow[dataColumn.ColumnName]) { int iColWidth = (int)(Graphics.MeasureString (dataRow.ItemArray[iCurrCol].ToString(), dataGrid.Font).Width); iWidth = (int)System.Math.Max(iWidth, iColWidth); } } columnStyle.Width = iWidth + 4; // Add the new column style to the table style. tableStyle.GridColumnStyles.Add(columnStyle); } // Add the new table style to the data grid. dataGrid.TableStyles.Add(tableStyle); } catch(Exception e) { MessageBox.Show(e.Message); } finally { Graphics.Dispose(); } }