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

Persisting Changes Made to a ReorderList

4.43/5 (3 votes)
29 Jun 20072 min read 1   546  
This article demonstrates a way to save changes made to the initial order presented in a ReorderList

Screenshot - PersistentReorderList1.jpg

Introduction

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

Background

The ReorderList control provides a very smooth cross-browser experience with dragable list items. However, it behaves quite differently from most other controls in the sense that accessing changes made to the list has no in-built property and requires some special treats!

I wanted to show a list to the visitors of my page and let them reorder it as necessary, saving the changed order when the page is submitted. However, while 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. 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

The database

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

Screenshot - PersistentReorderList2.jpg


Note that the Priority column determines the initial presentation order.

The WorkItem and WorkItemsHandler 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 SessionScope
    public static void SaveWorkItems(List<WorkItem> workItems)
    {
        HttpContext.Current.Session["WorkItems"] = workItems;
    }
}

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>

The EventHandler code

The sample application takes care of the following events in order to function properly.

Session_Start

Session_Start loads the WorkItems into the current session, as follows:

C#
void Session_Start(object sender, EventArgs e) 
{
    // Load WorkItems to the current session.
    WorkItemsHelper.LoadWorkItems();
}

Page_Load

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

rlWorkItems_ItemReorder saves the order as it is changed by 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

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

  1. ReorderList's DataSource expects an implementation of IList. So, if you supply it a DataTable instead, it will behave unexpectedly. It will show up for the first time, but will throw exceptions on subsequent post-backs.
  2. One can choose Application collection (HttpContext.Current.Application) or Cache (HttpContext.Current.Cache) instead of the Session if applicable.
  3. OnItemReorder must be registered and persistence mechanism must take place on this event handling routine.

History

  • June 24, 2007 - initial composition

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here