<%@ Page language="c#" AutoEventWireup="false" %> SandGrid Documentation

SandGrid User Guide

Working with Columns

Back to Table of Contents

Column Basics

A column is responsible for formatting data for display, parsing input for storage as data and displaying formatted values to the user. Any grid needs at least one column to be useful. Columns are always displayed from left to right, in the order they are added to the Columns collection unless an alternate display order has been specified or chosen by the user. They can be hidden from display programmatically.

Columns normally have visible headers, and they support HeaderText and HeaderImage properties.

To justify the text displayed in cells use the CellHorizontalAlignment and CellVerticalAlignment properties. These are set to Near and Center by default, respectively. You can also set the horizontal alignment of text displayed in the column header with the HeaderHorizontalAlignment property.

One column within a grid is designated the primary column. This is usually the first column, and the first column added is automatically assigned to the PrimaryColumn property. It is this column whose contents are indented in tree or nested-grid scenarios.


Every column has a Width property, which in the most basic of usage dictates the width, in pixels, of the column. By default a user can resize a column interactively. This behaviour is governed by the ResizeBehavior property, an enumeration with values of None, MoveFollowingElements or MaintainTotalWidth. The default behaviour is that when a column is resized the following columns move to the right or left, adjusting the total width of the grid. If the last option is chosen, the column immediately following the resized column has its width adjusted by an inverse amount so that the total width of the grid remains the same. You can use the MinimumWidth property to enforce a minimum width as the user resizes.

Sometimes you may wish a column to automatically assume the maximum display width of any data within. This can always be achieved interactively by the user by double-clicking the resize bar, but in other situations you may always want this to be enforced. To achieve this, set the AutoSize property to Contents. Note that there is a speed penalty for doing this: the column must measure the data in every cell when deciding how wide it should be. A companion property is AutoSizeIncludeHeader, which if set to true includes the column header contents in its calculation of width.

The other kind of automatic sizing is when a column expands to fill any remaining space left in the grid after all the fixed-width columns have been laid out. One or more columns can have their AutoSize property set to Spring. When multiple columns are sprung their relative widths are maintained proportionally to what they were at design time, so a column with a design-time width of 200 will always be twice as big as a column whose design-time width was 100, when the grid is resized.

User Interaction

Column headers can be clickable, and this is the case by default. To disable this, set the Clickable property to false. When a column header is clicked it raises the ColumnHeaderClick event on the parent grid, so your application can respond to this and do whatever it likes. The most common use for clicking a column header is to sort that column, and if the AutoSortType is set to a value other than None, this will happen automatically so there's no need to write this glue code yourself. So; columns are clickable by default and when clicked, they sort by default. Either of these behaviours can be changed with properties.

We have already covered sizing, but to reinterate, a column can be resized by the user when its ResizeBehavior property is set to a value other than None. It can always be sized to its contents by the user double-clicking on the resize indicator. There is also a SizeToContents method for doing this programmatically.

The final type of user interaction possible is reordering of the columns in a grid by dragging their headers. While dragging a column header an indicator appears in the grid between other columns as the cursor is moved around. To disable this behaviour set the AllowReorder property to false.


There is no user-interactive way of controlling the visibility of a column, but still there is a Visible property that can be used programmatically to toggle the visibility. The most common pattern for this is to display a context menu for a column header when the user right-clicks it and allow the toggling of visibility from there. Below is example code to open a context menu if the mouse is right-clicked over a column header.

private void sandGrid1_MouseUp(object sender, MouseEventArgs e)
	// Obtain the point under the mouse cursor, taking account of grid scrolling
	Point gridPoint = sandGrid1.PointToGrid(new Point(e.X, e.Y));
	// Find the column header under the cursor
	GridColumn column = sandGrid1.PrimaryGrid.HitTest(gridPoint) as GridColumn;
	if (column != null)
		mnuHide.Tag = column;
		contextMenuStrip1.Show(sandGrid1, new Point(e.X, e.Y));

private void mnuHide_Click(object sender, EventArgs e)
	GridColumn column = (GridColumn)mnuHide.Tag;
	column.Visible = false;

Obviously, because the column header is on longer visible it cannot be right-clicked to show again, so another menu option somewhere else in the application would be needed.

Programmatic Reordering

Reordering columns programmatically is possible too. It is impractical to change the actual order of columns in the Columns collection because then their indices would no longer correspond with those of the cells in rows. Therefore a separate numerical "display order" for columns is maintained, which by default is simply the same as their order within the Columns collection.

Rather than provide a numerical property per column we expose one single method on the Columns collection itself: SetDisplayIndices. This may appear needlessly complex but it prevents the ambiguity resulting from successive property sets on multiple columns and duplicate values. SetDisplayIndices takes an integer array and the number of elements in the array must match the number of columns in the grid. Each entry sets the display index for that column.

For example, say you have a grid with three columns A, B and C. Their order in the Columns collection is of course 0, 1 and 2 respectively. To change their order to B, C, A the following call should be made.

sandGrid1.Columns.SetDisplayIndices(new int[] { 2, 0, 1 });

State Serialization

As we have seen, there are a number of properties of a column that can be changed by the user, such as width, sort, display order and visibility. In a grid of any significant size, your application will probably wish to persist these settings between sessions. We help make this easier by providing SerializeState and DeserializeState methods. These two methods transform column settings to and from an XML representation in a string, which can obviously be stored anywhere by your application. The only requirement for doing this is that the same number of columns are present during deserialization as there were during serialization.

Here is a small example of using the serialization capabilities. It is not complete because the data needs to be stored somewhere. You might choose to use the registry or the file system for this.

private void frmTest_FormClosing(object sender, FormClosingEventArgs e)
	string state = sandGrid1.SerializeState();
	// TODO: Save this state to disk

private void frmTest_Load(object sender, EventArgs e)
	string state;
	// TODO: Load contents of state variable from disk

Next: Working with Rows