Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C#

DataGrid with Movable Rows

Rate me:
Please Sign up or sign in to vote.
4.33/5 (8 votes)
8 Oct 2009CPOL2 min read 57.2K   2.6K   21   11
The DataGridMovableRows control lets you move rows around in a DataGrid
Image 1

Introduction

The DataGridMovableRows control lets you move rows around in a DataGrid! We created it for our Gantt control implementation and decided to share it with the community.

The DataGridMovableRows control (deriving from DataGrid) allows the end user to select rows and simply drag them around to a new location. A visual drag cue is provided when the user moves the mouse over the row header of the selected row and visual cues are also provided to indicate drop location.

BeforeMovingRows and RowsMoved events are fired. RowsMoved will tell you which rows are being moved and to what new location. You could typically update your bound list to reflect this change, in this event handler.

Background

Our Silverlight Gantt control required a DataGrid with support for movable rows. This obviously was not supported internally by the DataGrid and so we had to implement it ourselves. This ended up being a non-trivial task due to customized scrolling behavior implemented in the DataGrid. As the grid is scrolled vertically, the top rows that are going out of view are actually getting hidden, rather than simply being scrolled out. This makes it very hard to determine the co-ordinates of a row so that the drag-cue and drop-cue can be rendered properly.

We created a new control DataGridMovableRows which encapsulates all the tracking details and presents you two simple event handlers as mentioned above, BeforeMovingRows and RowsMoved.

Note that the only way to persist the order of items in a table/list is to include a separate field, for example "SortOrder". This field should be updated accordingly as the user drags the rows around in a DataGrid. The attached sample uses this approach to persist the new order. This also means that before binding your table/list to the DataGrid, make sure to sort it by this "SortOrder" field.

Using the Code

To begin with, listen to the BeforeMovingRows event handler where you can optionally cancel the move based on what rows are selected. Then make the selected rows contiguous, the built-in logic does not support moving rows that are not adjacent, so this step is necessary.

C#
private void dataGrid1_BeforeMovingRows
	(object sender, System.ComponentModel.CancelEventArgs e)
{ // If the selected includes the first row, cancel the selection.
if (this.dataGrid1.SelectedItems.Contains(this.firstItem))
{ e.Cancel = true; return; }
// Make selected items contiguous.
this.FlattenSelection(); }

// If the user selected row 2 and row 5, then this method will also select row 3 and 4.
// This is necessary because the logic here assumes that all selected objects are
// adjacent to each other.
private void FlattenSelection()
{ int topRowIndex = Int32.MaxValue; int botRowIndex =Int32.MinValue; 
IList<CustomObject> list = this.dataGrid1.ItemsSource as IList<CustomObject>;
foreach (CustomObject item in this.dataGrid1.SelectedItems) 
		{ int index = list.IndexOf(item);
if (index < topRowIndex) topRowIndex = index; 
if (index > botRowIndex) botRowIndex = index; }
if (this.dataGrid1.SelectedItems.Count < (botRowIndex - topRowIndex + 1))
{ for (int i = topRowIndex; i <= botRowIndex; i++)
{ CustomObject o = list[i]; 
if (this.dataGrid1.SelectedItems.Contains(o)== false) 
	this.dataGrid1.SelectedItems.Add(o); } } }

Then listen to the RowsMoved event handler where you can adjust the order of the items as follows:

C#
void dataGrid1_RowsMoved(object sender, RowsMovedEventArgs args)
{ // args.StartIndex - The start index of the set of rows that are being moved
// args.Count - The number of adjacent rows below the start index that are being moved.
// args.DestinationIndex - The destination for this move
// Interpreting this move varies by the application.
// Here we will adjust the SortOrder of the bound objects and 
// then rebind them with the grid.
IList<CustomObject> list = this.dataGrid1.ItemsSource as IList<CustomObject>;
this.MoveInList(list, args.StartIndex, args.Count, args.DestinationIndex); }

// There are 2 ways to handle this:
// 1) Move items and adjust their SortOrder (this is the technique used here).
// 2) Another option is to just adjust the SortOrder 
// and then rebind the DataGrid with a new list
// that's properly sorted based on SortOrder.
public int MoveInList(IList<CustomObject> list, int start, int count, int dest) 
{ int from; int to; int newDestOfStart; 
if (dest > start) { from = start; to = dest - 1; 
for (int i = 0; i < count; i++) { CustomObject view = list[start]; 
list.RemoveAt(start); list.Insert(dest - 1, view); 
} 
newDestOfStart = dest - count; } 
else 
{ from = dest; to = start + count - 1; 
for (int i = 0; i < count; i++) 
{ CustomObject view = list[start + i]; 
list.RemoveAt(start + i); list.Insert(dest + i, view); } 
newDestOfStart = dest; } for (int i = from; i <= to; i++) 
{ ((CustomObject)list[i]).SortOrder = i; } 
return newDestOfStart; }

Points of Interest

We understand that being able to drag and drop rows from the grid into other controls is another useful scenario. If you are interested in this, please update the comments section and we will create a new article for this.

History

  • 7th October, 2009: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Product Manager RadiantQ
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionJust what I needed! Pin
Greg Lindberg15-Apr-13 6:56
Greg Lindberg15-Apr-13 6:56 
QuestionNo support for row detail template Pin
Member 94546543-Oct-12 4:47
Member 94546543-Oct-12 4:47 
GeneralAbout 'Ctrl' multiple selected, and some bug. Pin
pageup0084-Jun-12 23:01
pageup0084-Jun-12 23:01 
QuestionHow to increase row height? Pin
rj_sp28-Mar-12 2:09
rj_sp28-Mar-12 2:09 
AnswerRe: How to increase row height? Pin
kajalpatel15-Nov-12 2:57
kajalpatel15-Nov-12 2:57 
GeneralHelp Pin
nikhil123425-Nov-10 2:15
nikhil123425-Nov-10 2:15 
GeneralGood article. Have some issues Pin
zorrack1-Nov-10 5:46
zorrack1-Nov-10 5:46 
GeneralThanks for posting this Pin
Ray Loveless21-Sep-10 6:43
Ray Loveless21-Sep-10 6:43 
GeneralGood feature which is not provided in silverlight sdk [modified] Pin
shital@meenu24-Aug-10 20:36
shital@meenu24-Aug-10 20:36 
GeneralThis should be stantard Pin
Luc Archambault7-Feb-10 8:04
Luc Archambault7-Feb-10 8:04 
GeneralGood Keep going Pin
Ernesto Tejeda8-Oct-09 6:27
Ernesto Tejeda8-Oct-09 6:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.