Introduction
The ReorderList
is one of the coolest controls in the ASP.NET AJAX Control Toolkit. This article intends to give a basic outline of how to subclass the control so you can bind it to a DataTable
and, on a Reorder
event, save the new order to the database. There is no source code to download with this article, only code sighted within. The focus of this article is on the ReorderList
and not on saving and retrieving data from a database.
The Problem
The ReorderList
expects as it's DataSource
, an object that implements IList
. My business objects work mostly with DataSets
and DataTables
and I wanted to bind to a DataTable
. The control will load data from a DataTable
but on a Reorder
event an exception will be thrown stating the DataTable
does not implement IList
. I tried using ((IListSource)DataTable).GetList()
but that didn't go anywhere.
The Solution
To begin, create a subclass of the ReorderList
and override the DoReorder
method like this:
using System;
using System.Data;
using AjaxControlToolkit;
namespace My.Web.UI.Controls
{
public class myReorderList : ReorderList
{
protected override bool DoReorder(int oldIndex, int newIndex)
{
if (DataSource is DataTable)
{
DataRowCollection rows = ((DataTable)DataSource).Rows;
int NewListOrder = (int)rows[newIndex][SortOrderField];
if (oldIndex < newIndex)
{
for (int i = oldIndex + 1; i <= newIndex; i++)
{
rows[i][SortOrderField] =
(int)rows[i][SortOrderField] - 1;
}
}
else
{
for (int i = oldIndex - 1; i >= newIndex; i--)
{
rows[i][SortOrderField] =
(int)rows[i][SortOrderField] + 1;
}
}
rows[oldIndex][SortOrderField] = NewListOrder;
return true;
}
else
{
throw new InvalidOperationException
("DataSource is not a System.Data.DataTable.");
}
return false;
}
}
}
Here is some example code for an aspx page that is almost exactly like the code found in ReorderList.aspx in the Samples project of the ASP.NET AJAX Control Toolkit. The one exception is the addition of OnItemReorder="ReorderList1_ItemReorder"
. Also notice SortOrderField="Priority"
. This indicates the name of the column in the data source DataTable
that stores the item's order in the group. This property is used in the overridden DoReorder
method in the subclass (sighted above) to store the new order. The subclassed control expects this column to be an int
column.
<MyAjaxToolkit:myReorderList ID="ReorderList1" runat="server"
PostBackOnReorder="false"
CallbackCssStyle="callbackStyle"
DragHandleAlignment="Left"
ItemInsertLocation="End"
DataKeyField="ItemID"
SortOrderField="Priority"
OnItemReorder="ReorderList1_ItemReorder">
<ItemTemplate>
<div class="itemArea">
<asp:Label ID="Label1" runat="server"
Text='<%# HttpUtility.HtmlEncode(Convert.ToString(Eval("Title"))) %>' />
<asp:Label ID="Label2" runat="server"
Text='<%# HttpUtility.HtmlEncode(Convert.ToString(Eval("Description", " - {0}"))) %>' />
</div>
</ItemTemplate>
<EditItemTemplate>
<div class="itemArea">
<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("Title") %>' />
<asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("Description") %>' />
<asp:TextBox ID="TextBox4" runat="server" Text='<%# Bind("Priority") %>' />
</div>
</EditItemTemplate>
<ReorderTemplate>
<asp:Panel ID="Panel2" runat="server" CssClass="reorderCue" />
</ReorderTemplate>
<DragHandleTemplate>
<div class="dragHandle"></div>
</DragHandleTemplate>
<InsertItemTemplate>
<div style="padding-left:25px; border-bottom:thin solid transparent;">
<asp:Panel ID="panel1" runat="server" DefaultButton="Button1">
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Title") %>' />
<asp:Button ID="Button1" runat="server" CommandName="Insert" Text="Add" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="Please enter some text" ControlToValidate="TextBox1" />
</asp:Panel>
</div>
</InsertItemTemplate>
</MyAjaxToolkit:myReorderList>
Then in the code behind the aspx page, we need something like this:
protected void Page_Load(object sender, EventArgs e)
{
ReorderList1.ItemDataBound +=
new EventHandler<AjaxControlToolkit.ReorderListItemEventArgs>
(ReorderList1_ItemDataBound);
if (!IsPostBack)
{
BindReorderList();
}
else
{
}
}
void BindReorderList()
{
ReorderList1.DataSource = SomeDataTable;
ReorderList1.DataBind();
}
protected void ReorderList1_ItemReorder(object sender,
AjaxControlToolkit.ReorderListItemReorderEventArgs e)
{
BindReorderList();
}