Column and Row Resizing
The default appearance vof the DataGridView is a modest improvement over the DataGrid. But with a few quick refinements, you can greatly improve it.
One problem is that the DataGridView gives a default standard width to all columns regardless of their content. As a result, the initial appearance of the bound grid in Figure 15-1 is less than perfect, with the ModelName and Description columns too small for the data they contain.
Fortunately, you can use some powerful automatic resizing functionality that's built into the DataGridView. Your first decision is whether you want to control sizing for the entire control or fine tune individual columns. The following sections explore your options.
Setting an Automatic Resize Mode for the Entire Grid
The simplest approach is to set a resizing behavior that applies to all columns using the AutoSizeColumnsMode property. Your options are shown in Table 15-4.
Table 15-4. AutoSizeColumnsMode Values
Value
Description
None AllCells
AllCellsExceptHeader
ColumnHeader
DisplayedCells
DisplayedCellsExceptHeader Fill
The column widths are not adjusted automatically. Extra content is clipped (with an ellipsis added to indicate the missing content). This is the default.
Each column is sized just large enough to fit the largest value, including header cells.
Each column is sized just large enough to fit the largest value, excluding header cells.
Each column is sized just large enough to fit the text in the header.
Similar to AllCells, except the DataGridView only considers the rows that are currently visible at the time the property is set. This option is used to improve performance for large grids. The assumption is that the first subset of values has a fairly representative set of widths.
The same as DisplayedCells, except it doesn't take the header cell into consideration.
Column widths are adjusted so that all columns exactly fill the available DataGridView. If the grid is resized, all the columns change proportionately. You can adjust the MinimumWidth and FillWeight properties of each column to make some columns wider than others.
■Tip Using the AllCells criteria to sort a small table works perfectly well. However, if you have an extremely large table (one with thousands of rows), it introduces a noticeable delay because the width of every value in the table needs to be examined. In these cases, it much more practical to compromise and use the DisplayedCells value instead. This only examines the width of the values in the rows that are currently visible in the DataGridView.
Setting the AutoSizeColumnsMode at any time triggers the DataGridView to resize its columns immediately. Figure 15-6 shows a simple test application in action, changing the grid from AutoSizeColumnsMode.None to AutoSizeColumnsMode.Fill and then to AutoSizeColumnsMode.DisplayCells (in which case the last column is too wide to fit in the grid, and scroll bars are added).
If you use Fill mode, users are still allowed to resize columns (assuming you haven't changed the Resizable property of any DataGridViewColumn objects). When a column is resized, all the following columns are expanded or shrunk proportionately to fit the remaining space. If you resize the last column, all the other columns are resized proportionately.
- Figure 15-6. Automatic column resizing in the DataGridView
Setting an Automatic Resize Mode for Individual Columns
If you don't want all columns to be resized in the same way, you can adjust the AutoSizeMode property of the DataGridViewColumn object for each column. For example, you could size one column to None and another column to DisplayedCells. (The default value is NotSet, in which case the value is inherited from the DataGridView.AutoSizeColumnsMode property.)
A more interesting scenario occurs if you're using proportional fill. In many cases, you'll want to make some columns larger than others or limit them so they can't shrink beyond a certain minimum. This is easy to accomplish through the FillWeight and MinimumWidth properties.
Initially, the FillWeight of every column is 100. If you set the FillWeight of another column to 200, you create a column that's twice as wide. A FillWeight of 50 is half as large as the default. The FillWeight is only important in a relative sense, unlike the MinimumWidth property, which sets an absolute minimum width in pixels.
Here's an example that configures these details:
// Retrieve the columns you need to work with. DataGridViewColumn colID = dataGridView1.Columns["ProductID"]; DataGridViewColumn colModel = dataGridView1.Columns["ModelName"]; DataGridViewColumn colDesc = dataGridView1.Columns["Description"];
// Give much more weigth to the description. colID.FillWeight = 25; colModel.FillWeight = 25; colDesc.FillWeight = 100;
// However, keep a minimum width that ensures // the first two columns are readable. // Another option in this scenario is to only // assign fill mode to the description column. colID.MinimumWidth = 75; colModel.MinimumWidth = 125; colDesc.MinimumWidth = 100;
■Note Unfortunately, you must configure column properties using code. Although the DataGridView does provide design-time support for modifying the Columns property, unless you're using the automatic data-binding features discussed in Chapter 8 (which aren't suitable for most large-scale projects), you won't be able to add or modify bound columns.
When the user resizes a column, the FillWeight changes. As a result, additional resize operations (on other columns or the whole grid) will work a little differently. For example, if the user expands the first column, it's automatically given a correspondingly larger FillWeight. If the user then resizes the whole form (and by extension, the DataGridView), the first column gets the same larger proportion of space.
There's no need to use Fill mode with every column. You can use Fill mode with just one column. The fill behavior still works the same—the remaining space in the DataGridView is divided among all Fill mode columns.
■Tip If you don't want to use Fill mode for the whole grid, but you want to make sure the DataGridView background isn't visible, you can configure the last column to spring to fill the remaining space. All you need to do is set the AutoSizeColumnsMode of that column to Fill.
Manual Sizing
Automatic resizing is preferred because it's the most flexible approach. However, you can use fixed pixel widths instead. Just set the AutoSizeColumnsMode to None (either for individual columns or for the entire grid) and then set the DataGridViewColumn.Width property with the width in pixels.
User Sizing
By default, the DataGridView allows the user to resize columns that have an AutoSizeColumnsMode of None or Fill. If you are using another option (like DisplayedCells), resizing is disabled. (However, you'll learn how to work around this limitation in the next section.)
If you want to prevent the user from resizing columns or rows altogether, set the AllowUserToResizeRows and AllowUserToResizeColumns properties for your DataGridView to false. You also can restrict the user from resizing individual columns or rows by setting the Resizable property of the corresponding DataGridViewColumn or DataGridViewRow.
Programmatic Resizing
The DataGridView also allows you to trigger autosizing for specific columns or the entire grid by calling one of the following methods:
• AutoResizeColumn()
• AutoResizeColumns()
• AutoResizeRows()
• AutoResizeColumnHeadersHeight()
• AutoResizeRowHeadersWidth()
There are a couple of common reasons that you might choose to use these methods. First of all, there is a possible performance consideration. The DataGridView performs automatic column resizing at several points, including after a column sort and a cell edit. If you've used a resize mode like AllCells, this could be impractically slow. In this case, you might choose to perform your sorting exactly when you want it by calling the appropriate method.
Another reason you might use programmatic resizing is to get around the problem that automatically resized columns don't allow user resizing. If you use a resize mode other than None or Fill, the user won't be able to adjust the column widths. This might be a problem in some situations—for example, if you want the user to be able to collapse a column to see more information without scrolling. To get around this problem, you can leave the default resizing mode to None, but call one of the resizing methods when the form first loads. Here's an example that resizes the third column:
dataGridView1.AutoResizeColumn(2, DataGridViewAutoSizeColumnMode.AllCells);
And here's an example that resizes the whole grid:
dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnMode.AllCells);
Keep in mind that this method needs to be invoked after you bind the data, or it won't have any effect. You also might want to use it after user editing (perhaps in response to an event like DataGridView.CellValueChanged).
Resizing Rows
The DataGridView provides a similar model for resizing rows. Your options are identical to those shown in Table 15-4, and you can resize the height all the rows in the grid or specific rows automatically or manually. The only difference is the name of the properties and methods that you use. For example, the AutoSizeRowsMode property configures automatic resizing for the DataGridView, and the DataGridViewRow.Height property allows you to set a specific pixel height.
There are only three reasons that you'll want to resize a row:
• You've enlarged the font size, so the text is being clipped at the bottom. (Similarly, if you reduce the font size, you might resize the row to get rid of the extra space.)
• You're using a different column type, like an image, and the content extends beyond the bounds of the standard row height.
• You're using wrapped text, and you want to show several lines at once.
The first two options are fairly straightforward. Wrapped text is a little more interesting. It works through the style model described in the next section. The basic approach is that you set the columns that you want to wrap. Then, you set the column width. Finally (and optionally), you use automatic row resizing to heighten the row to fit all the text.
Here's an example that ensures you can always see the lull description text. The Description column is set to use DataGridViewAutoSizeColumnMode.Fill, and the automatic row size adjusts the row height as necessary.
DataGridViewColumn colDesc = dataGridView1.Columns["Description"]; // Give it as much width as possible.
colDesc.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; // Wrap to fit the bounds of the column.
colDesc.DefaultCellStyle.WrapMode = DataGridViewTriState.True; // Use row autosizing to show all the text.
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells; Figure 15-7 shows how this grid adapts as it is resized.
In this example, the automatic row resizing only takes displayed cells into consideration. Try the same example (included online) with AllCells resizing, and you'll notice more lethargic performance.
■Note You'll see the DataGridViewTriState enumeration used in some places where you might expect to find ordinary Boolean values. The three values are True, False, and NotSet (which inherits values from the containing object). For example, a value of NotSet allows a cell to inherit settings from a row, the row to inherit them from the grid, and so on.
- Figure 15-7. Resizing rows to fit wrapped text
Post a comment