DataGrid Customization Part-IV:Exchanging a DataGrid Columns using Drag and Drop

This is the part 4 of a multi part series of articles. In this series, I am exploring the functionality of Windows Forms DataGrid control.

Here are previous three parts:

DataGrid Customization Part 1
DataGrid Customization Part 2
DataGrid Customization Part 3

In this article, I will show you how to exchange two  DataGrid columns by dragging and dropping.

You probably have noticed this functionality in third part grid controls. You drag a DataGrid column and drop it on another column and position of these two columns exchange. This is what I will do here. For example, in the following figure, if you drag ContactName column on top of ContactTitle table, position of these columns should be exchanged.

DataGr1.gif

Figure 1. Customized DataGrid part 4

The functionality of drag and drop is implemented on DataGrid's mouse down and mouse up event handlers. On mouse down, we need to store the column style, which is being dragged and on mouse up event handler, we need to find out the current column, where the dragged column was dropped.

Once you know both the columns, its now turn to exchange the columns. Unfortunately, there is no direct property or method, which can change the index of a DataGrid columns.

This all will be done by using the DataGridTableStyle and DataGridColumnStyle. These two classes are discussed in DataGrid Customization Part 2 in more details.

The code for DataGrid.MouseDown event handler is listed in the following Listing:

private void dataGrid1_MouseDown(object sender,System.Windows.Forms.MouseEventArgs e)
{
// If left mouse button clicked
if(e.Button == MouseButtons.Left)
{
if(hti.Type == DataGrid.HitTestType.ColumnHeader)
{
this.Cursor = new Cursor("HandCur.cur");
dataGrid1.ContextMenu = columnHeadMenu;DataGridColumnStyle col =
gridStyle.GridColumnStyles[hti.Column];
dcStyle = gridStyle.GridColumnStyles[hti.Column];
firstColIndex = gridStyle.GridColumnStyles.IndexOf(col);
dragDropInAction =
true;
}
}
}

The code for DataGrid.MouseUp event handler is listed in the following Listing. As you can see from this code, first we get the current column by using the MouseEventArgs's X and Y values. After that I find out the index of the current column in the DataGrid and make call ReshuffleColumns. The ReshuffleColumns method takes four arguments - source column index, destination column index, DataTable mapping name, and the DataGrid control ID.

private void dataGrid1_MouseUp(object sender,System.Windows.Forms.MouseEventArgs e)
{
if (!dragDropInAction)
return;
// If left mouse button clicked
if(e.Button == MouseButtons.Left)
{
Point pt =
new Point(e.X, e.Y);
DataGrid.HitTestInfo hti = dataGrid1.HitTest(pt);
// Get the current column
DtaGridTableStyle gridStyle = dataGrid1.TableStyles["Customers"];
if(hti.Type == DataGrid.HitTestType.ColumnHeader)
{
dataGrid1.ContextMenu = columnHeadMenu;
DataGridColumnStyle col = gridStyle.GridColumnStyles[hti.Column];
dcStyle = gridStyle.GridColumnStyles[hti.Column];
lastColIndex = gridStyle.GridColumnStyles.IndexOf(col);
}
ReshuffleColumns(firstColIndex, lastColIndex, "Customers", dataGrid1);
this.Cursor = Cursors.Default;
}
dragDropInAction =
false;
}

Now let's take a look at ReshuffleColumns method listed in the following listing. As you can see from this code, I store the DataColumn style of source and destination columns by using the GridColumnStyle and the index of columns. I create a copy of existing DataTable style and copies existing style to a new style accept the two columns. If current column index matches with any of the source or destination columns, I exchange them. When the column index is source, I add destination column style and vice versa.

public void ReshuffleColumns(int col1, int col2, string mapName, DataGrid grid)
{
// Store the exisitng style
DataGridTableStyle existingTableStyle = grid.TableStyles[mapName];
// Store both original columns
DataGridColumnStyle dgCol1 = existingTableStyle.GridColumnStyles[col1];
DataGridColumnStyle dgCol2 = existingTableStyle.GridColumnStyles[col2];
int counter = existingTableStyle.GridColumnStyles.Count;
// Create a new DataGrid table style
DataGridTableStyle newTableStyle = new DataGridTableStyle();
newTableStyle.MappingName = mapName;
// Copy every thing as it is accept the columsn that are involved in exchange process
for(int i = 0; i < counter; ++i)
{
if(i == col1)
newTableStyle.GridColumnStyles.Add(existingTableStyle.GridColumnStyles[col2]);
else if(i == col2)
newTableStyle.GridColumnStyles.Add(existingTableStyle.GridColumnStyles[col1]);
else
newTableStyle.GridColumnStyles.Add(existingTableStyle.GridColumnStyles[i]);
}
// Remove the existing table style and add new style
grid.TableStyles.Remove(existingTableStyle);
grid.TableStyles.Add(newTableStyle);
}

To understand more, download the source code and run the application.

I will continue exploring more functionality of DataGrid. If you know any cool trick like this, don't forget to share with us.

Cheers!

Mahesh


Mindcracker
Founded in 2003, Mindcracker is the authority in custom software development and innovation. We put best practices into action. We deliver solutions based on consumer and industry analysis.