Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Realtime Reordering Using the ASP.NET AJAX Control Toolkit’s ReorderList Control with LINQ to SQL

4.50/5 (5 votes)
3 Sep 2008CPOL 1   1.8K  
An article on using LINQ to SQL with the ASP.NET AJAX Control Toolkit’s ReorderList control.

Introduction

The ReorderList is a very powerful piece of the ASP.NET AJAX Control Toolkit. It gives you the ability to interactively reorder a list of items.

Article.jpg

The Problem

I put together this demonstration to go over how to wire the ASP.NET AJAX Toolkit’s ReorderList control to a LINQ to SQL data source. Out of the box, the ReorderList control gives you the ability to easily reorder items in a list on the client side. Where I found it fell short was in how the reordering changes that you make get committed back to the database.

The Solution

I created a fairly straightforward way to commit reordering changes back to the database at the time the reorder event takes place. In doing this, the reordering changes you make get committed to the database in real-time, as opposed to making a bunch of changes and clicking a Reorder button. I believe this is a much better way of doing it because there is a lower chance of changes getting lost, and this helps resolve contention issues in a multi-user reordering scenario.

The web page:

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="RealtimeReorderList.aspx.cs"
    Inherits="RealtimeReorderlist.RealtimeReorderList" %>

<%@ Register Assembly="AjaxControlToolkit" 
  Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<!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">
    <link rel="Stylesheet" type="text/css" 
       href="ReorderList.css" />
    <title>Realtime Reorderable List Using LINQ to SQL</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <fieldset>
                    <legend>Reorderable List Items</legend>
                    <div style="width: 850px">
                        <div class="reorderListDemo" 
                               style="padding-bottom: 50px">
                            <ajaxToolkit:ReorderList ID="rlItemList" 
                                  DragHandleAlignment="Left" 
                                  PostBackOnReorder="true"
                                  CallbackCssStyle="callbackStyle" 
                                  ItemInsertLocation="End" 
                                  ShowInsertItem="false"
                                  runat="server">
                                <DragHandleTemplate>
                                    <div class="dragHandle">
                                    </div>
                                </DragHandleTemplate>
                                <ItemTemplate>
                                    <div class="itemArea">
                                        <span style="float: right">
                                            <asp:Button Width="50" ID="Button3" 
                                              CommandName="Delete" 
                                              runat="server" Text="Delete" />
                                        </span>
                                        <asp:Label ID="ID" Visible="false" 
                                          runat="server" 
                                          Text='<%# Eval("ID") %>'></asp:Label>

                                        <asp:Label ID="Order" Visible="false" 
                                          runat="server" 
                                          Text='<%# Eval("ListOrder") %>'></asp:Label>
                                        <asp:Label ID="Name" runat="server" 
                                          Text='<%# Eval("Name") %>'></asp:Label>:  
                                        <asp:Label ID="Label1" runat="server" 
                                          Text='<%# Eval("Description") %>'></asp:Label>
                                    </div>
                                </ItemTemplate>
                                <ReorderTemplate>
                                    <asp:Panel ID="Panel2" runat="server" 
                                       CssClass="reorderCue" />
                                </ReorderTemplate>
                            </ajaxToolkit:ReorderList>
                        </div>
                    </div>
                </fieldset>
                <fieldset>
                    <legend>Add List Item</legend>
                    <div>
                        <asp:TextBox ID="tbItemName" 
                                 runat="server"></asp:TextBox>
                        <ajaxToolkit:TextBoxWatermarkExtender ID="TBWE1" 
                            runat="server" TargetControlID="tbItemName"
                            WatermarkText="Name" 
                            WatermarkCssClass="watermarkTextBox" />
                    </div>
                    <div>
                        <asp:TextBox Rows="4" ID="tbItemDescription" 
                          runat="server" Height="51px" 
                          TextMode="MultiLine"></asp:TextBox>
                        <ajaxToolkit:TextBoxWatermarkExtender ID="TBWE2" 
                          runat="server" 
                          TargetControlID="tbItemDescription"
                          WatermarkText="Description" 
                          WatermarkCssClass="watermarkTextBox" />
                    </div>
                    <div>
                        <asp:Button ID="btnAddReorderListItem" 
                          runat="server" Text="Add" 
                          OnClick="AddReorderListItem_Click" />
                    </div>
                </fieldset>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

The code-behind:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;

namespace RealtimeReorderlist
{
    public partial class RealtimeReorderList : System.Web.UI.Page
    {
        protected int NewListOrderNumber;
        protected List<reorderlistitem> ListDataItems;

        protected void Page_Load(object sender, EventArgs e)
        {

            rlItemList.ItemReorder += new EventHandler<reorderlistitemreordereventargs>
                                          (rlItemList_ItemReorder);

            // Event handler for deleting items from the list
            rlItemList.ItemCommand += new EventHandler<reorderlistcommandeventargs>
                                          (rlItemList_ItemCommand);

            GetListData();
            if (!Page.IsPostBack)
                BindData();
        }


        /// <summary>
        /// Reorder list items in the database when a reorder event occurs
        /// </summary>
        protected void rlItemList_ItemReorder(object sender, 
                       ReorderListItemReorderEventArgs e)
        {
            var NewOrder = e.NewIndex + 1;
            var OldOrder = e.OldIndex + 1;

            var ReorderListItemID = Convert.ToInt32(((Label)(
                e.Item.FindControl("ID"))).Text);

            var db = new RealTimeReorderListDataDataContext();

            var ListItemCount = 1;

            var ListData = from ld in db.ReorderListItems
                           orderby ld.ListOrder
                           select ld;
            foreach (var ListDataItem in ListData)
            {
                // Move forward items in this range
                if (OldOrder > NewOrder
                    && ListItemCount >= NewOrder
                    && ListItemCount <= OldOrder
                    )
                    ListDataItem.ListOrder = ListItemCount + 1;
                // Move backward items in this range
                else if
                    (OldOrder < NewOrder
                    && ListItemCount <= NewOrder
                    && ListItemCount >= OldOrder
                    )
                    ListDataItem.ListOrder = ListItemCount - 1;

                ListItemCount++;

                // Set the changed item into the newly numerical gap
                if (ListDataItem.ID == ReorderListItemID)
                    ListDataItem.ListOrder = NewOrder;
            }

            db.SubmitChanges();

            GetListData();
            BindData();
        }


        /// <summary>
        /// ItemCommand event used to delete list items
        /// </summary>
        void rlItemList_ItemCommand(object sender, ReorderListCommandEventArgs e)
        {
            // If you want support for multiple commands
            if (e.CommandName != "Delete")
                return;

            var db = new RealTimeReorderListDataDataContext();

            var ListData = from ld in db.ReorderListItems
                           where ld.ID == Convert.ToInt32(((Label)
                              (e.Item.FindControl("ID"))).Text)
                           select ld;
            db.ReorderListItems.DeleteAllOnSubmit(ListData);
            db.SubmitChanges();
            GetListData();
            BindData();
        }


        /// <summary>
        /// Add button click event used to inset a new list item into the database
        /// </summary>
        protected void AddReorderListItem_Click(object sender, EventArgs e)
        {
            GetListData(); // Get the current NewListOrderNumber
            var db = new RealTimeReorderListDataDataContext();
            var RLI = new ReorderListItem
            {
                ListOrder = NewListOrderNumber,
                Name = tbItemName.Text,
                Description = tbItemDescription.Text
            };
            db.ReorderListItems.InsertOnSubmit(RLI);
            db.SubmitChanges();
            
            // Clear the form values so that watermark shows
            tbItemName.Text = "";
            tbItemDescription.Text = "";

            GetListData(); //Get the list with the newly inserted item
            BindData();

        }

        /// <summary>
        /// Retrieve the list items from the database
        /// </summary>
        protected void GetListData()
        {
            var db = new RealTimeReorderListDataDataContext();
            var ListData = from ld in db.ReorderListItems
                           orderby ld.ListOrder
                           select ld;
            ListDataItems = ListData.ToList();
            NewListOrderNumber = ListDataItems.Count() + 1;
        }

        /// <summary>
        /// Bind the data the to the ReorderList control
        /// </summary>
        protected void BindData()
        {
            rlItemList.DataSource = ListDataItems;
            rlItemList.DataBind();
        }

    }
}

The SQL schema:

SQL
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ReorderList](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ListOrder] [int] NULL,
    [Name] [nvarchar](256) NULL,
    [Description] [nvarchar](4000) NULL,
 CONSTRAINT [PK_ReorderList] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
  IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
  ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

License

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