- DataGridView Overview
- Basic Data Binding with the DataGridView
- Controlling Modifications to Data in the Grid
- Programmatic DataGridView Construction
- Custom Column Content with Unbound Columns
- Displaying Computed Data in Virtual Mode
- Using the Built-In Column Types
- Built-In Header Cells
- Handling Grid Data Edits
- Automatic Column Sizing
- Column and Row Freezing
- Using the Designer to Define Grids
- Column Reordering
- Defining Custom Column and Cell Types
- Utilizing Cell-Oriented Grid Features
- Formatting with Styles
- Where Are We?
Column Reordering
Column reordering is a slick built-in behavior of the grid that lets users change the display order of columns in the grid at runtime. Because different users of an application often pay more attention to some columns in a grid than others, users commonly request to set the order of the columns displayed in the grid themselves. While you could support this functionality by programmatically removing columns from the grid and then inserting them back in the new position, that requires a fair amount of tedious code to have to write for a common use case. So the Windows Client team was nice enough to build functionality for this right into the grid control.
The way this works is that if the AllowUserToOrderColumns property is set to true and the user clicks and drags on a column header, the grid lets them drag and drop the column to the position where they would like it to display. The columns to the right of the drop position will move one position to the right, and the columns surrounding the original location of the dragged column will move to be adjacent after the column has been moved. Figure 6.6 shows this in action. In this case, the QuantityPerUnit column was clicked on and is being dragged to the left. A gray box is drawn the size of the column’s header cell you are dragging. When you move the cursor to one side of another column, the border between that column and the adjacent one darkens, indicating where the column you are dragging will be placed if you release the mouse button.
Figure 6.6 Column Recording in Action
When a column has been moved through column reordering, its ColumnIndex doesn’t change, but the DisplayIndex property indicates its current display order within the grid. By default, the display order of the grid is not persisted between application runs, but it’s a simple matter to persist that information yourself and reinstate the display order by writing the display order to a file. The code in Listing 6.3 demonstrates persisting the data into a file in isolated storage using the XmlSerializer class.
Example 6.3. Persisting Display Order of Columns
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { m_Grid.AllowUserToOrderColumns = true; SetDisplayOrder(); } private void OnFormClosing(object sender, FormClosingEventArgs e) { CacheDisplayOrder(); } private void CacheDisplayOrder() { IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForAssembly(); using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("DisplayCache", FileMode.Create, isoFile)) { int[] displayIndices =new int[m_Grid.ColumnCount]; for (int i = 0; i < m_Grid.ColumnCount; i++) { displayIndices[i] = m_Grid.Columns[i].DisplayIndex; } XmlSerializer ser = new XmlSerializer(typeof(int[])); ser.Serialize(isoStream,displayIndices); } } private void SetDisplayOrder() { IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForAssembly(); string[] fileNames = isoFile.GetFileNames("*"); bool found = false; foreach (string fileName in fileNames) { if (fileName == "DisplayCache") found = true; } if (!found) return; using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("DisplayCache", FileMode.Open, isoFile)) { try { XmlSerializer ser = new XmlSerializer(typeof(int[])); int[] displayIndicies = (int[])ser.Deserialize(isoStream); for (int i = 0; i < displayIndicies.Length; i++) { m_Grid.Columns[i].DisplayIndex = displayIndicies[i]; } } catch { } } } }
This code isn’t specific to the data source in any way. The key facets here are that the code in the form Load event handler sets the AllowUserToOrderColumns property to true, allowing the dynamic changing of DisplayIndex for columns through drag-and-drop operations. I then added a CacheDisplayOrder helper method that is called by the Form.Closing event handler, and a SetDisplayOrder helper method that is called when the form loads.
CacheDisplayOrder first collects all the display index values for each of the grid’s columns and puts them into an integer array. It then creates an isolated storage file stream and writes the array to that stream using the XmlSerializer class. The SetDisplayOrder method does the reverse: it first checks to see if the file exists, and if so, reads the array back in and uses it to set the DisplayIndex on each column in the grid.