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:
- The database
- The
WorkItem
and WorkItemsHandler
classes - The ReorderList markup code
- The EventHandler code
The database
My sample database has only one table named WorkItems with the following sample data:
Note that the Priority column determines the initial presentation order.
The WorkItem and WorkItemsHandler classes
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);
}
}
public class WorkItemsHelper
{
public static void LoadWorkItems()
{
HttpContext.Current.Session["WorkItems"] =
WorkItemsHelper.GetWorkItems();
}
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"];
}
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)
{
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)
{
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)
{
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)
{
divMessage.InnerHtml = "New Order <hr />";
foreach (WorkItem item in WorkItemsHelper.GetWorkItems())
{
divMessage.InnerHtml += item.ToString()+"<br />";
}
}
Important issues
- 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. - One can choose Application collection (
HttpContext.Current.Application
) or Cache (HttpContext.Current.Cache
) instead of the Session if applicable. OnItemReorder
must be registered and persistence mechanism must take place on this event handling routine.
History
- June 24, 2007 - initial composition