Example E4582
Visible to All Users

Grid View for ASP.NET Web Forms - Reorder Grid Rows Using Buttons and Drag-and-Drop

This example demonstrates how to use buttons and jQuery drag-and-drop functionality to reorder rows in ASPxGridView.

ASPxGridView - ReorderGridRows

Set up the grid and create an invisible column that stores row order indices. Sort the grid by this column and disable sorting at the control level.

XML
<dx:ASPxGridView ID="gvProducts" runat="server" ...> <Columns> ... <dx:GridViewDataTextColumn FieldName="DisplayOrder" Visible="false" SortIndex="0" SortOrder="Ascending" /> </Columns> <SettingsBehavior AllowSort="false" ... /> ... </dx:ASPxGridView>

When a user clicks the button or drags and drops a row, the grid sends a callback to the server, sets the invisible column value to a new row order index, and updates the grid data.

Files to Look At

Documentation

More Examples

Example Code

Default.aspx
ASPx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <%@ Register Assembly="DevExpress.Web.v15.1, Version=15.1.15.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web" TagPrefix="dx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript" src="https://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script> <script src="jquery.ui.touch-punch.min.js"></script> <style> .hover { background-color: lightblue; } .activeHover { background-color: lightgray; } .ui-draggable-dragging { background-color: lightgreen; color: White; } </style> <script type="text/javascript"> var states = []; function InitalizejQuery() { $('.draggable').draggable({ helper: 'clone', start: function (ev, ui) { var $draggingElement = $(ui.helper); $draggingElement.width(gridView.GetWidth()); } }); $('.draggable').droppable({ activeClass: "hover", tolerance: "intersect", hoverClass: "activeHover", drop: function (event, ui) { var draggingSortIndex = ui.draggable.attr("sortOrder"); var targetSortIndex = $(this).attr("sortOrder"); MakeAction("DRAGROW|" + draggingSortIndex + '|' + targetSortIndex); } }); } function UpdatedGridViewButtonsState(grid) { btMoveUp.SetEnabled(grid.cpbtMoveUp_Enabled); btMoveDown.SetEnabled(grid.cpbtMoveDown_Enabled); } function gridView_Init(s, e) { UpdatedGridViewButtonsState(s); } function gridView_EndCallback(s, e) { UpdatedGridViewButtonsState(s); NextAction(); } function btMoveUp_Click(s, e) { MakeAction("MOVEUP"); } function btMoveDown_Click(s, e) { MakeAction("MOVEDOWN"); } function MakeAction(action) { if (gridView.InCallback()) states.push(action) else gridView.PerformCallback(action) } function NextAction() { if (states.length != 0) { var currentState = states.shift(); if (currentState == "MOVEUP" && gridView.cpbtMoveUp_Enabled) gridView.PerformCallback(currentState); else if (currentState == "MOVEDOWN" && gridView.cpbtMoveDown_Enabled) gridView.PerformCallback(currentState); else if (currentState.indexOf("DRAGROW") != -1) gridView.PerformCallback(currentState); else NextAction(); } } </script> </head> <body> <form id="form1" runat="server"> <div> <table> <tr> <td rowspan="2"> <dx:ASPxGridView ID="gvProducts" runat="server" OnHtmlRowPrepared="gvProducts_HtmlRowPrepared" DataSourceID="dsProducts" ClientInstanceName="gridView" AutoGenerateColumns="False" KeyFieldName="ProductID" OnCustomCallback="gvProducts_CustomCallback" OnCustomJSProperties="gvProducts_CustomJSProperties"> <ClientSideEvents Init="gridView_Init" /> <Columns> <dx:GridViewDataTextColumn FieldName="ProductID" ReadOnly="True" VisibleIndex="0"> <EditFormSettings Visible="False" /> </dx:GridViewDataTextColumn> <dx:GridViewDataTextColumn FieldName="ProductName" VisibleIndex="1"> </dx:GridViewDataTextColumn> <dx:GridViewDataTextColumn FieldName="DisplayOrder" Visible="false" VisibleIndex="2" SortIndex="0" SortOrder="Ascending"> </dx:GridViewDataTextColumn> <dx:GridViewDataTextColumn FieldName="UnitPrice" ShowInCustomizationForm="True" VisibleIndex="3"> </dx:GridViewDataTextColumn> </Columns> <Styles> <Row CssClass="draggable"></Row> </Styles> <SettingsBehavior AllowSort="false" AllowFocusedRow="true" ProcessFocusedRowChangedOnServer="True" /> <SettingsPager Mode="ShowAllRecords" /> <ClientSideEvents Init="gridView_Init" EndCallback="gridView_EndCallback" /> </dx:ASPxGridView> </td> <td class="style1" style="vertical-align: bottom"> <dx:ASPxButton ID="btMoveUp" runat="server" Text="Up" Width="100px" AutoPostBack="false"> <ClientSideEvents Click="btMoveUp_Click" /> </dx:ASPxButton> </td> </tr> <tr> <td class="style1" style="vertical-align: top"> <dx:ASPxButton ID="btMoveDown" runat="server" Text="Down" Width="100px" AutoPostBack="false"> <ClientSideEvents Click="btMoveDown_Click" /> </dx:ASPxButton> </td> </tr> </table> <asp:AccessDataSource ID="dsProducts" runat="server" DataFile="~/App_Data/nwind.mdb" SelectCommand="SELECT TOP 10 [ProductID], [ProductName], [DisplayOrder], [UnitPrice] FROM [Products]" UpdateCommand="UPDATE Products SET [DisplayOrder] = ? where [ProductID] = ?"> <UpdateParameters> <asp:Parameter Name="DisplayOrder" /> <asp:Parameter Name="ProductID" /> </UpdateParameters> </asp:AccessDataSource> <asp:AccessDataSource ID="dsHelper" runat="server" DataFile="~/App_Data/nwind.mdb" SelectCommand="SELECT [ProductID] FROM [Products] where [DisplayOrder] = ?"> <SelectParameters> <asp:Parameter Name="DisplayOrder" /> </SelectParameters> </asp:AccessDataSource> <dx:ASPxGlobalEvents ID="ge" runat="server"> <ClientSideEvents ControlsInitialized="InitalizejQuery" EndCallback="InitalizejQuery" /> </dx:ASPxGlobalEvents> </div> </form> </body> </html>
Default.aspx.cs(vb)
C#
using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using DevExpress.Web; public partial class _Default : System.Web.UI.Page { void UpdateGridViewButtons(ASPxGridView gridView) { gridView.JSProperties["cpbtMoveUp_Enabled"] = gridView.FocusedRowIndex > 0; gridView.JSProperties["cpbtMoveDown_Enabled"] = gridView.FocusedRowIndex < (gridView.VisibleRowCount - 1); } int GetGridViewKeyByVisibleIndex(ASPxGridView gridView, int visibleIndex) { return (int)gridView.GetRowValues(visibleIndex, gridView.KeyFieldName); } protected void gvProducts_CustomJSProperties(object sender, ASPxGridViewClientJSPropertiesEventArgs e) { ASPxGridView gridView = sender as ASPxGridView; UpdateGridViewButtons(gridView); } private int GetKeyIDBySortIndex(ASPxGridView gridView, int sortIndex) { dsHelper.SelectParameters["DisplayOrder"].DefaultValue = sortIndex.ToString(); int rowKey = (int)(dsHelper.Select(DataSourceSelectArguments.Empty) as System.Data.DataView)[0][gridView.KeyFieldName]; return rowKey; } private void UpdateSortIndex(int rowKey, int sortIndex) { dsProducts.UpdateParameters["ProductID"].DefaultValue = rowKey.ToString(); dsProducts.UpdateParameters["DisplayOrder"].DefaultValue = sortIndex.ToString(); dsProducts.Update(); } protected void gvProducts_CustomCallback(object sender, DevExpress.Web.ASPxGridViewCustomCallbackEventArgs e) { ASPxGridView gridView = sender as ASPxGridView; string[] parameters = e.Parameters.Split('|'); string command = parameters[0]; if (command == "MOVEUP" || command == "MOVEDOWN") { int focusedRowKey = GetGridViewKeyByVisibleIndex(gridView, gridView.FocusedRowIndex); int index = (int)gridView.GetRowValues(gridView.FocusedRowIndex, "DisplayOrder"); int newIndex = index; if (command == "MOVEUP") { newIndex = (index == 0) ? index : index - 1; } if (command == "MOVEDOWN") { newIndex = (index == gridView.VisibleRowCount) ? index : index + 1; } int rowKey = GetKeyIDBySortIndex(gridView, newIndex); UpdateSortIndex(focusedRowKey, newIndex); UpdateSortIndex(rowKey, index); gridView.FocusedRowIndex = gridView.FindVisibleIndexByKeyValue(rowKey); } if (command == "DRAGROW") { int draggingIndex = int.Parse(parameters[1]); int targetIndex = int.Parse(parameters[2]); int draggingRowKey = GetKeyIDBySortIndex(gridView, draggingIndex); int targetRowKey = GetKeyIDBySortIndex(gridView, targetIndex); int draggingDirection = (targetIndex < draggingIndex) ? 1 : -1; for (int rowIndex = 0; rowIndex < gridView.VisibleRowCount; rowIndex++) { int rowKey = GetGridViewKeyByVisibleIndex(gridView, rowIndex); int index = (int)gridView.GetRowValuesByKeyValue(rowKey, "DisplayOrder"); if ((index > Math.Min(targetIndex, draggingIndex)) && (index < Math.Max(targetIndex, draggingIndex))) { UpdateSortIndex(rowKey, index + draggingDirection); } } UpdateSortIndex(draggingRowKey, targetIndex); UpdateSortIndex(targetRowKey, targetIndex + draggingDirection); } gridView.DataBind(); } protected void gvProducts_HtmlRowPrepared(object sender, ASPxGridViewTableRowEventArgs e) { if (e.RowType == GridViewRowType.Data) { object rowOrder = e.GetValue("DisplayOrder"); if (rowOrder != null) e.Row.Attributes.Add("sortOrder", rowOrder.ToString()); } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.