Click here to Skip to main content
Email Password   helpLost your password?

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

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

/// 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

<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:

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:

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:

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:

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

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralThanks for sharing
GreggS
8:27 29 Nov '07  
This was really an excellent post.
Thank you for taking the time to write it.
Your post helped me out of a jam.





Gregg

Generalvb reorderlist
mmm!@#
16:36 24 Sep '07  
hi,
is there any vb code for reorder list?.....thanks Big Grin
AnswerRe: vb reorderlist
S. M. SOHAN
18:54 24 Sep '07  
Thanks for your interest.
I don't know of a vb code. But I guess you can convert the code to vb with a little effort and it should work if done in similar fashion.




Had you not been blessed with your eyes, you would miss the colors of life. So, donate posthumous eye and bring color to the lives of the deprived friends.

GeneralAwesome!
keith_fra
8:53 24 Jul '07  
This is exactly what I 'almost' need, I am pretty new at this stuff.

I have this working just fine.

What if I wanted to be able to add / delete items off this list?

What would be the best way to approach this?
Generaldatasource = null
corymillican
13:06 13 Jul '07  
Hi
I am trying some very similar code but when I post back the reorderlist has lost the new order. I also tried changing a session/viewstate in the OnItemReorder method but the reorderlist.datasource is null when I do the callback. Any ideas why I am loosing the order?

thanks
GeneralRe: datasource = null
expinch
11:54 28 Sep '07  
I am having the exact same problem, checking the value of reorderlist.datasource in the 'OnItemReorder' eventhandler and it is null. Are we to believe that this property will have the updated order when the page is posted back? I don't see it.

I'd also like to hear what is necessary to get the sample running as I'm getting run errors.
GeneralRe: datasource = null
Programmers
17:14 9 Oct '07  
Me too. I am binding it to a collection that is generated using a NetTiers generated collection of TList that implements IList.

Anyone who can help me work out why this is happening it would be greatly appreciated
AnswerRe: datasource = null
chrcha
6:10 14 Nov '07  
Ensure your initial DataBind is not in (!IsPostBack)!

ChrisSmile
QuestionRe: datasource = null
Fantini
4:01 1 Feb '08  
I have the same problem. I bind my data only the first time page is loaded(!IsPostBack). But a I have two problems:

1- I lose previous order;
2- The ItemReorder method is not called.

My aspx page:

<asp:ReorderList ID="rlOpzioniSondaggio" runat="server" ShowInsertItem="true" DragHandleAlignment="Left" ItemInsertLocation="Beginning" EnableViewState="true" DataKeyField="IdOpzione" SortOrderField="IntPosizione" OnItemReorder="rlOpzioniSondaggio_ItemReorder" PostBackOnReorder="true" >
....
</asp:ReorderList>

My aspx.cs class

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{     
OpzioniSondaggio bllOpzioniSondaggio = new OpzioniSondaggio();
//Bind the ReorderList
rlOpzioniSondaggio.DataSource = bllOpzioniSondaggio.GetOpzioniSondaggio(idSondaggio);
rlOpzioniSondaggio.DataBind();
}
}

protected void rlOpzioniSondaggio_ItemReorder(object sender, AjaxControlToolkit.ReorderListItemReorderEventArgs e)
{
OpzioniSondaggio bllOpzioniSondaggio = new OpzioniSondaggio();
//Item Reordered, so save the current order to the application scope               bllOpzioniSondaggio.SaveOpzioniSondaggio(
(List<RomagnaOggi.admin.CODE.OpzioneSondaggio>) rlOpzioniSondaggio.DataSource) ;

}

THX in advance.

Renzo
GeneralGood Post
kazimanzurrashid
11:03 1 Jul '07  
Very goodpost, but i am wondering why you need a submit buton to persist the changes? Can You handle the changes on drop?

Long Live .NET
Amit

GeneralRe: Good Post
S. M. SOHAN
7:47 3 Jul '07  
Thank you for the complement.
The order is saved only after the submit button is pressed, because, my target was to let the user play with the list items and finally save the changes!

Had you not been blessed with your eyes, you would miss the colors of life. So, donate posthumous eye and bring color to the lives of the deprived friends.

GeneralRe: Good Post
keith_fra
11:26 25 Jul '07  
S.M. SOHAN

I am using your script to do some prototyping for a client. I had a question regarding the btnSubmit_Click() function. I dont see where this actually gets written back to the database.

I have the sample working fine, but my values are not getting saved to the DB, only in session.

Thoughts?

Thanks,
Keith


Last Updated 29 Jun 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010