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

Persisting changes made to the ASP.NET AJAX ReorderList

3.45/5 (8 votes)
23 Jun 2007CPOL2 min read 1   572  
The ASP.NET AJAX ReorderList has no in-built property to retrieve the changes made in the client side. This article shows a workaround to this problem.

Screenshot - PersistentReorderList1.jpg

Introduction

This article demonstrates how to use the ASP.NET AJAX ReorderList with the capability to retrieve/save the changes made to it.

Background

The ReorderList control provides a very smooth cross-browser experience with draggable list items. However, it behaves quite differently than most other controls in the sense that, accessing changes made to the list is not a built-in feature and requires some special treats! I wanted to show a list of visitors on my page, reorder it as necessary, and save the changed order when the page is submitted. However, surfing the internet I found it hard to get a clear solution. I hope this article will help someone with similar needs.

Using the code

This article is described in terms of the code, and for better understanding, I have divided the code into necessary parts as follows:-

  1. The database
  2. The WorkItem and WorkItemsHandler classes
  3. The ReorderList markup code
  4. The EventHandler code

1. The database

My sample database has only one table named WorkItems, with the following sample data:

The ReorderList Order Saved

Note: The Priority column determines the initial presentation order (ascending).

2. The WorkItem and WorkItemsHelper classes

C#
/////////////////////////////////////////////
/// Code fragment from App_Code/WorkItem.cs 
/////////////////////////////////////////////

public class WorkItem
{
    public WorkItem(int itemID, int priority, string title, string description)
    {
        _ItemID         = itemID;
        _Priority       = priority;
        _Title          = title;
        _Description    = description;
    }

    private int _ItemID;
    public int ItemID
    {
        get { return _ItemID;  }
        set { _ItemID = value;  }
    }

    private int _Priority;
    public int Priority
    {
        get { return _Priority; }
        set { _Priority = value; }
    }

    private string _Title;
    public string Title
    {
        get { return _Title; }
        set { _Title = value; }
    }

    private string _Description;
    public string Description
    {
        get { return _Description; }
        set { _Description = value; }
    }

    public override string ToString()
    {
        return string.Format("Item: ID:{0}\tPriority:{1}\tTitle{2}" + 
               "\tDecription{3}", _ItemID, _Priority, _Title, _Description);
    }
}

/////////////////////////////////////////////

/// Code fragment from App_Code/WorkItemsHelper.cs 

/////////////////////////////////////////////

public class WorkItemsHelper
{    
    //Loads the Work items to the Session Scope

    public static void LoadWorkItems()
    {        
        HttpContext.Current.Session["WorkItems"] =  
                                    WorkItemsHelper.GetWorkItems();
    }
    //Returns the WorkItems - either from database 
    //        or from Session scope (if its there!)

    public static List<WorkItem> GetWorkItems()
    {
        if (HttpContext.Current.Session["WorkItems"] == null)
        {

            DataTable table = new WorkItemsTableAdapter().GetWorkItems();
            List<WorkItem> workItems = new List<WorkItem>();
            foreach (DataRow row in table.Rows)
            {
                workItems.Add(new WorkItem(int.Parse(row["ItemID"].ToString()),
                                           int.Parse(row["Priority"].ToString()),
                                           row["Title"].ToString(),
                                           row["Description"].ToString()));
            }
            return workItems;
        }
        return (List<WorkItem>)HttpContext.Current.Session["WorkItems"];
    }
    //Save the workItems to the Session Scope

    public static void SaveWorkItems(List<WorkItem> workItems)
    {
        HttpContext.Current.Session["WorkItems"] = workItems;
    }
}

3. The ReorderList markup code

ASP.NET
<div class="ClsReorderListContainer">
    <ajaxToolkit:ReorderList ID="rlWorkItems" runat="server" DragHandleAlignment="Left"
          ItemInsertLocation="Beginning" DataKeyField="ItemID" SortOrderField="Priority"
          EnableViewState="true" OnItemReorder="rlWorkItems_ItemReorder" 
          CallbackCssStyle="ClsCallBackStyle">
        <ItemTemplate>
            <div class="ClsItemArea">
                <table style="width: 100%;">
                    <tr>
                        <td class="ClsItem">
                            <asp:Label ID="Title" runat="server" 
                                       Text='<%# Eval("Title") %>'></asp:Label>
                            <asp:Label ID="Description" runat="server" 
                                       Text='<%# Eval("Description") %>'></asp:Label>
                        </td>
                    </tr>
                </table>
            </div>
        </ItemTemplate>
        <ReorderTemplate>
            <asp:Panel ID="Panel2" runat="server" CssClass="ClsReorderCue">
            </asp:Panel>
        </ReorderTemplate>
        <DragHandleTemplate>
            <div class="ClsDragHandle">
            </div>
        </DragHandleTemplate>
    </ajaxToolkit:ReorderList>
</div>

4. The EventHandler code

This sample application takes care of the following events to function properly:

  • Session_Start: Loads the WorkItems to the current session.
  • C#
    void Session_Start(object sender, EventArgs e) 
    {
        // Load WorkItems to the current session.
    
        WorkItemsHelper.LoadWorkItems();
    }
  • Page_Load: Binds the ReorderList with data each time the page is loaded.
  • C#
    protected void Page_Load(object sender, EventArgs e)
    {
        //Bind the ReorderList - its a must
    
        rlWorkItems.DataSource = WorkItemsHelper.GetWorkItems();
        rlWorkItems.DataBind();
    }
  • rlWorkItems_ItemReorder: Saves the new order as it is changed at the client.
  • C#
    protected void rlWorkItems_ItemReorder(object sender, 
              AjaxControlToolkit.ReorderListItemReorderEventArgs e)
    {
        //Item Reordered, so save the current order to the Session scope
    
        WorkItemsHelper.SaveWorkItems((List<WorkItem>)rlWorkItems.DataSource);
    }
  • btnSubmit_Click: Shows the new order to the browser.
  • C#
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        //Show the current order
    
        divMessage.InnerHtml = "New Order <hr />";
        foreach (WorkItem item in WorkItemsHelper.GetWorkItems())
        {
            divMessage.InnerHtml += item.ToString()+"<br />";
        }
    }

Important issues

  • The ReorderList's DataSource expects an implementation of IList. So, supplying it a DataTable instead will behave unexpectedly and show up and error for the first time, but only throws exceptions on subsequent postbacks.
  • One can choose the Application collection (HttpContext.Current.Application) or the Cache (HttpContext.Current.Cache) instead of the Session, if applicable.
  • OnItemReorder must be registered, and the persistence mechanism must take place on this event handling routine.

History

  • June 24, 2007 - initial composition date.

License

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