Sorting the Order

Moving GridView Rows Up and Down




Sorting the Order

Moving GridView Rows Up and Down


By Alexey Smirnov


Sometimes it is necessary to have some sort of functionality enabling the user to change the sorting order of rows in a table. For instance, you may have a product catalog that lists products in the GridView control in order based on color and texture. To be able to sort and grade in that way you would need to assign a sorting index to each product item and store it in the database. There are a number of ways to accomplish this task in a .NET way but if you find them inconvenient or unattractive, you should try the approach we are going to discuss here. Although this is not a pure .NET technique, it may prove to be very useful to you in your .NET programming.


The idea of this example is not to perform processing of each change on the server and avoid reload each time the new sort index is adjusted. Using client-side code will allow users to perform and see all changes in a real time, and postback to the server only once when changes must be saved to the database.


Editing behavior starts with double-clicking a row in the GridView. The selected row can be moved up and down using the Up and Down arrow keys. When sorting on the client has been completed, the result will be sent to the server to save updated sorting indexes in the database.


So, suppose now we have a GridView full of data from the database. To make double-clicking on a row work, we need to modify the code-behind class and use the RowDataBound event to add the call of a client-side method. This would highlight the selected row on double-click. Also, in the RowDataBound event handler, we would add the id attribute to each GridView row that later would be used to identify the rows.


protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)


 if (e.Row.RowType == DataControlRowType.DataRow)


   e.Row.Attributes.Add("id", "r_" + ((GridView)sender).DataKeys[e.Row.RowIndex].Value);

   e.Row.Attributes.Add("ondblClick", "SelectRow(this);");



Figure 1: Handling the RowDataBound event of the GridView.


Now we can start with client-side coding. First, let s add a SelectRow method we call on double-click, and another service method called GetRows that returns an array of all rows in the grid. As you can see, SelectRow gets the row where the user clicked and changes its background to red. The previously selected row will be deselected. The currentRowId represents the index of a currently selected row.


var currentRowId = null;

// Highlight new row

function SelectRow(obj)


 var rows = GetRows();

 if (currentRowId != null)

     rows[currentRowId].style.backgroundColor = '#ffffff';

 currentRowId = obj.rowIndex-1;  // Using 0-based index

 rows[currentRowId].style.backgroundColor = '#ff0000';  


// Return all rows

function GetRows()


 var strTagName='tr';

 var arrElements = (strTagName == "*" && document.all)? document.all :


 var arrReturnElements = new Array();

 var oElement;

 for(var i=0; i<arrElements.length; i++)


   oElement = arrElements[i];

   if ('r_') == 0)





 return (arrReturnElements);


Figure 2: Client-side code to highlight a selected row.


To capture arrow keys events we need to add a listener that can handle events from the arrow keys. Note that there are some differences in implementation of this code between browsers; for instance, in IE you must use attachEvent rather than the W3C standard addEventListener (to support Firefox).


if (document.addEventListener){

 document.addEventListener('keydown', KeyDown, false); /*Firefox*/

} else if (document.attachEvent){

 document.attachEvent('onkeydown', KeyDown); /*IE*/

// Hook keystrokes

function KeyDown()


 if (currentRowId == null)


 var e = window.event/*IE*/ || arguments[0]/*Firefox*/;

 if (e.keyCode == 40) // Down Key

   MoveRow (currentRowId+1);

 else if (e.keyCode == 38) // Up Key



Figure 3: Event listener to capture input from a keyboard.


The KeyDown method will check which key is pressed (the Up key has keyCode = 38; the Down key has keyCode = 40) and will call the new MoveRow method with the currentRowId as an argument. If the Up key is pressed, the current position must be decreased by 1; if the Down key is pressed, the position must be increased by 1. Then, in the MoveRow method the current row will be cloned and deleted from the table. After that, the cloned row will be inserted above of the previous row (if the Up key was pressed), or below the next one (if the Down key was pressed). If the end of the table has been reached, the highlighted row will stop to move.


// Move row up/down

function MoveRow(rowId)


   var rows = GetRows();


   if (rowId<0 || rowId>rows.length-1)


   var newRow = rows[currentRowId].cloneNode('true');

   var delRow = rows[currentRowId];


   var p = delRow.parentNode;



   var row2 = null;


   if (currentRowId < rowId) { // Go down

     if (rowId+1<rows.length) {

       row2 = rows[rowId+1];


   } else {

     row2 = rows[rowId]; // Go up





   currentRowId = rowId; 

Figure 4: Client-side method to move selected row.


That s all for coding the marking and moving rows within the grid.


The last thing here would be another small piece of client and server code for saving to the database changes made in the grid. To do this, we also need to add a hidden form field (in this example, a HiddenField control) that will be used to access the client-side values from server-side code.


Suppose we have a Save button on the form. We can wire up the OnClientClick event of that button to call a client script right before form has been submitted back to the server. The client script will be used to enumerate all rows in the table, create a string with ids of all rows and their current position, and assign a value of the hidden field to this string. Note that client script must be injected by <%= HiddenField1.ClientID%> to get the id ASP.NET gives the server control on the client.


// Enumerate all rows and set hidden field

function SetHiddenField()


 var ret = '';

 var rows = GetRows();

 for (i=0;i<rows.length;i++)


   // Get item id from the row id

   var numb = rows[i].id.match(/\d+/);

   ret += i+':'+numb+';'


 // Set hidden field

 document.getElementById('<%=HiddenField1.ClientID%>').value = ret;


Figure 5: The complete client-side method to assign hidden field.


Once the button has been clicked, the client-side code will assign the value of the hidden field and ASP.NET will perform the postback where we can get the changes performed in the table.


protected void LinkButton1_Click(object sender, System.EventArgs e)


   string sortingString = HiddenField1.Value;

   if (sortingString == null || sortingString == string.Empty)


   string[] pairs = sortingString.Split(";".ToCharArray());

   foreach (string pair in pairs)


       string[] vals = pair.Split(":".ToCharArray());

       if (vals.Length == 2)


          Response.Write("id=" + vals[1] + ", order=" + vals[0]);

          Response.Write("<br />");




   // Save to database

   // ...

   // Refresh GridView

   // ...


Figure 6: Server-side code to get changes.


Well, that s probably all with the example. The client script is working now and the server method receives the adjusted sorting index to save it in the database. The only thing is that if you have many rows to adjust, you might get tired of switching between the mouse and keyboard. To make our method more professional and user-friendly, we should add support for moving the rows by using the mouse wheel.


/* Initialization for mouse wheel */

if (window.addEventListener)

 window.addEventListener('DOMMouseScroll', MouseWheelMove, false);

window.onmousewheel = document.onmousewheel = MouseWheelMove;

function MouseWheelInOut(delta) {

 if (delta >= 0)





function MouseWheelMove(event){

 if (currentRowId == null)


 var delta = 0;

 if (!event) event = window.event;

 if (event.wheelDelta) {

    delta = event.wheelDelta/120;

    if (window.opera) delta = -delta;

 } else if (event.detail) {

    delta = -event.detail/3;


 if (delta)


     if (event.preventDefault)


   event.returnValue = false;


Figure 7: Support for moving the rows by using the mouse wheel.



In this article, we explored how to extend the functionality of the GridView with  client-side code to deliver end users a more responsive Web interface.


Source code accompanying this article is available for download.


Alexey Smirnov is an IT Consultant,and a Microsoft MVP. You can contact him at mailto:[email protected].





Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.