Click here to Skip to main content
15,885,278 members
Articles / Web Development / ASP.NET
Tip/Trick

ASP.NET Gridview with Row Drag and Drop using Jquery TableDnD

Rate me:
Please Sign up or sign in to vote.
4.70/5 (5 votes)
17 Sep 2014CPOL3 min read 29K   1.3K   12   2
This article describes how to implement row drag and drop inside ASP.NET Gridview using Jquery TableDnD plugin and how to pass reordered sequence back to server

Introduction

ASP.NET Gridview by default does not provide a way to drag and drop rows. This can be achived using Jquery TableDnD plugin  https://github.com/isocra/TableDnD/tree/master/stable 

Background

While Jquery TableDnD plugin is fantastic way to allow end users to rearrange data in GridView the issue arise when that rearranged data needs to be sent back to server. As all the manipulation on the GridView is done using JavaScript server will not have a clue about rearranged data/rows.
This tip describes a way to overcome this issue so you can pass the reordered values back to the server and preserve the changes done by user on the client side.

Using the code

1.Create ASP.NET Web Application project in Visual Studio. First of all, we will create a DTO class to hold some data that we can display in a gridview. For this demo, I have created a DTO class of outstanding orders that contains some properties and some dummy data.

C#
//Some calss to hold data for gridview.
[Serializable]
public class Outstanding
{
    public int SequenceId { get; set; }
    public int RecordId { get; set; }

    public string Item { get; set; }
    public string Order { get; set; }
    public int Line { get; set; }
    public int Status { get; set; }
    public string ToLocation { get; set; }
    public decimal Qty { get; set; }
    public DateTime RegDate { get; set; }
    public string Location { get; set; }
    public decimal AllocQty { get; set; }


    public List<outstanding> GetOutstanding()
    {
        List<outstanding> lstOrders = new List<outstanding>();

        lstOrders.Add(new Outstanding() { SequenceId=1, RecordId = 5000, Item = "CocaCola", Order = "000101", Line = 1, Status = 20, ToLocation = "Sydney", Qty = 2000, RegDate = new DateTime(2014, 1, 1), Location = "USA", AllocQty = 100 });
        lstOrders.Add(new Outstanding() { SequenceId = 3, RecordId = 5001,Item = "BubbleGum", Order = "000101", Line = 1, Status = 20, ToLocation = "Sydney", Qty = 2500, RegDate = new DateTime(2014, 1, 11), Location = "USA", AllocQty = 300 });
        lstOrders.Add(new Outstanding() { SequenceId = 4, RecordId = 5002, Item = "Coffee", Order = "000111", Line = 1, Status = 50, ToLocation = "Melbourne", Qty = 2500, RegDate = new DateTime(2014, 1, 10), Location = "USA", AllocQty = 100 });
        lstOrders.Add(new Outstanding() { SequenceId = 5, RecordId = 5003, Item = "Sugar", Order = "000112", Line = 1, Status = 50, ToLocation = "Melbourne", Qty = 2300, RegDate = new DateTime(2014, 1, 10), Location = "NZ", AllocQty = 300 });
        lstOrders.Add(new Outstanding() { SequenceId = 8, RecordId = 5004, Item = "Milk", Order = "000112", Line = 1, Status = 50, ToLocation = "Melbourne", Qty = 2300, RegDate = new DateTime(2014, 1, 10), Location = "NZ", AllocQty = 200 });
        lstOrders.Add(new Outstanding() { SequenceId = 9, RecordId = 5005, Item = "Green Tea", Order = "000112", Line = 1, Status = 20, ToLocation = "Melbourne", Qty = 300, RegDate = new DateTime(2014, 1, 10), Location = "NZ", AllocQty = 220 });
        lstOrders.Add(new Outstanding() { SequenceId = 10, RecordId = 5006, Item = "Biscuit", Order = "000131", Line = 1, Status = 70, ToLocation = "Perth", Qty = 200, RegDate = new DateTime(2014, 1, 12), Location = "IND", AllocQty = 10 });
        lstOrders.Add(new Outstanding() { SequenceId = 11, RecordId = 5007, Item = "Wrap", Order = "000131", Line = 1, Status = 20, ToLocation = "Perth", Qty = 2100, RegDate = new DateTime(2014, 1, 12), Location = "IND", AllocQty = 110 });
        return lstOrders;
    }
}

2.In Default.aspx page in the header section add a reference to JavaScript libraries Jquery and TableDnD plugin

<script src="Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.tablednd.js" type="text/javascript"></script>

3. Add a Grdiview to the Default.aspx page inside an UpdatePanle and create BoundColumns to display Outstanding Order data.

 <asp:UpdatePanel ID="upnlOutstanding" runat="server" ChildrenAsTriggers="true" UpdateMode="Conditional"><br />
                    <ContentTemplate><br />
                        <h4><br />
                            Outstanding Orders</h4><br />
                                               <asp:GridView ID="grdViewOutstanding" runat="server" AutoGenerateColumns="False"<br />
                            BackColor="White" BorderColor="#999999" BorderStyle="Solid" CellPadding="5" ForeColor="Black"<br />
                            GridLines="Both" AllowPaging="True" CellSpacing="1" EmptyDataText="No outstanding orders found"<br />
                            CssClass="Grid" PageSize="10" AllowSorting="true" OnPageIndexChanging="grdViewOutstanding_PageIndexChanging"<br />
                             ><br />
                            <FooterStyle BackColor="#CCCCCC" /><br />
                            <Columns><br />
                                <asp:BoundField DataField="SequenceId" HeaderText="SequenceId"  /><br />
                                <asp:BoundField DataField="Item" HeaderText="Item" /><br />
                                <asp:BoundField DataField="Order" HeaderText="Order" /><br />
                                <asp:BoundField DataField="Line" HeaderText="Line" /><br />
                                <asp:BoundField DataField="Status" HeaderText="Status" /><br />
                                <asp:BoundField DataField="ToLocation" HeaderText="ToLocation" /><br />
                                <asp:BoundField DataField="Qty" HeaderText="Qty" /><br />
                                <asp:BoundField DataField="RegDate" HeaderText="RegDate" DataFormatString="{0:dd/MM/yyyy}" /><br />
                                <asp:BoundField DataField="Location" HeaderText="Location" /><br />
                                <asp:BoundField DataField="AllocQty" HeaderText="AllocQty" /><br />
                                <asp:BoundField DataField="RecordId" HeaderText="RecordId" /><br />
                            </Columns><br />
                            <PagerStyle HorizontalAlign="Center" CssClass="pgr" /><br />
                            <SelectedRowStyle BackColor="#000099" Font-Bold="True" ForeColor="White" /><br />
                            </asp:GridView><br />
                    </ContentTemplate><br />
                </asp:UpdatePanel>

4.Now in the Page_Load event, we will bind gridview to the dummy data. I have kept data in ViewState for this demo.

C#
<code>
         protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                Outstanding objOutstanding = new Outstanding();
                List<outstanding> lstOutstandingOrders = new List<outstanding>();
                lstOutstandingOrders = objOutstanding.GetOutstanding();
                grdViewOutstanding.DataSource = lstOutstandingOrders;
                grdViewOutstanding.DataBind();

                ViewState["lstOutstandingOrders"] = lstOutstandingOrders;
                upnlOutstanding.Update();
            }
        }
</code>

5.In the Default.aspx page add two hidden fields ( For the purpose of the demo I have made these input fields as text fields so you can view what is going on with the fields. To hide the fields from display change its type from text to hidden). These fields will be used to track which rows are being dragged and the new sequence number for the items. As there is no direct way to let server know that row order for GridView has changed theses two fields will keep a track of changes and that information will be passed to the server on postback.

HTML
<code>
 <label for="eleNewSeq">New Sequence </label> <input id="eleNewSeq"  runat="server" style="width:100%" type="text" value="" />
 <label for="eleDragged">Record Dragged </label>  <input id="eleDragged"  runat="server" style="width:100%" type="text" value="" />
 </code>

6.Now add a script tag in Default.aspx page and apply tableDnD to the GridView in document ready jquery function $(); When you start dragging the row it will apply "DragTableRow" css class to the row that is being dragged. As you can notice there is a onDrop function which will get called when you drop the row. In this function we get the row that was being dragged and get the value of RecordId from it. This value is than gets added to the two hidden fields. I have used ":" as a seperator for fields so I can use one input element to keep track of all the recordIds that are being resequenced. You can call an Ajax function here and update the server instantly but to prevent multiple calls to the serve I have added a button to the Default.aspx page and on its click all the information will go back to the server and application will do the resequencing of data.

JavaScript
<code>

 
               $(document).ready(function () {
                $("#<%= grdViewOutstanding.ClientID %>").tableDnD({
                    onDragClass: "DragTableRow",
                    onDrop: function (table, row) {

                        var rows = table.tBodies[0].rows, newOrder = '', dragged = '';
                        dragged = $('#<%= eleDragged.ClientID %>').val();
                        dragged += row.cells[10].innerText == undefined ? row.cells[10].textContent : row.cells[10].innerText + ":";
                        for (var i = 1; i < rows.length; i++) {
                            newOrder += rows[i].cells[10].innerText == undefined ? rows[i].cells[10].textContent : rows[i].cells[10].innerText + ":";
                        }
                        $('#<%= eleNewSeq.ClientID %>').val(newOrder);
                        $('#<%= eleDragged.ClientID %>').val(dragged);
                    }
                });
            });
 </code>

7.Add logic to do the resounding on the server on "Update Order Sequence" button's click event

C#
<code>

     protected void btnUpdateOrderSequence_Click(object sender, EventArgs e)
        {
            int recordId = 0;
            int seq = 0;
            Dictionary<int, int=""> recordIdSeq = new Dictionary<int, int="">();
            List<int> recordIds = new List<int>();
            List<int> sequences = new List<int>();
         
            foreach (GridViewRow row in grdViewOutstanding.Rows)
            {
                seq = int.Parse(row.Cells[0].Text.Trim());
                sequences.Add(seq); // List of Sequence Id
            }

            if (!string.IsNullOrEmpty(eleNewSeq.Value)) // New Sequenced RecordIds
            {
                string[] allNewOrderdRecordId = eleNewSeq.Value.Trim().Split(':'); // Get New Order of Record Ids
                for (int i = 0; i < allNewOrderdRecordId.Length; i++)
                {
                    if (int.TryParse(allNewOrderdRecordId[i], out recordId))
                    {
                        recordIds.Add(recordId);
                    }
                }
            }
            if (recordIds.Count > 0)
            {
                sequences.Sort();
                for (int i = 0; i < recordIds.Count; i++)
                {
                    recordIdSeq.Add(recordIds[i], sequences[i]); //Setup new order -> Which sequenceId is assinged to which Record
                }
            }
            //For the purpose of this demo this manipulation is done on the viewstate data. Ideally you may want to save the new sequencing in the database and rebind gridview
             if (ViewState["lstOutstandingOrders"] != null)
             {
                List<outstanding> lstOutstandingOrders = (List<outstanding>)ViewState["lstOutstandingOrders"];
                List<outstanding> lstOutStandingResequenced = new List<outstanding>();
                int i = 0;
                foreach (Outstanding objTemp in lstOutstandingOrders)
                {
                    objTemp.SequenceId = recordIdSeq[objTemp.RecordId];  // Assign New Sequence Id 
                    i++;
                    lstOutStandingResequenced.Add(objTemp);
                }
                if (lstOutStandingResequenced.Count > 0)
                {
                    lstOutStandingResequenced = lstOutStandingResequenced.OrderBy(x => x.SequenceId).ToList();
                    ViewState["lstOutstandingOrders"] = lstOutStandingResequenced;
                    grdViewOutstanding.DataSource = lstOutStandingResequenced;
                    grdViewOutstanding.DataBind();
                    upnlOutstanding.Update();
                }

            }


          

        }
</code>

Points of Interest

This is one way of passing re-sequenced GridView rows back to the server.

License

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


Written By
Software Developer (Senior)
Australia Australia
I am currently working as a Software Developer in .NET technologies.

Languages & Technologies I have worked on so far:

Pascal ... My first programming language..baby steps..
8085 Assembler ... Amazing how it all works internally in computer brain... "intel inside"
C... missing my point(er)....
C++... Its all about classes ...
LISP ... Did I missed any parenthesis ?
VB... Oh dear... Just like a war stories.. those are the days
Java... I learn to program this in notepad...
C#... Oh what a smooth sailing...
ASP.NET... web is the future ...
Oracle ... Not the one from "The Matrix"...
MSSQL... select Programming from Universe where StartTime >='BigBang'
Wireless Sensor Networks ... Look who is talking too ?

Comments and Discussions

 
QuestionDrag between two grids? Pin
Martin Plamondon3-Feb-15 9:08
Martin Plamondon3-Feb-15 9:08 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun18-Sep-14 1:57
Humayun Kabir Mamun18-Sep-14 1:57 

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.