Hi everyone,
Recently I had a requirement in which the users needed to be able to select items from one sorted RadListBox control (Source) and move them to another RadListBox control (Destination). In the Destination box, the users also needed to be able to put the items in any order they wanted. To make matters a little more complicated, the Destination box was pre-populated with some items marked as "required", and the users were not supposed to be able to move those items out of the Destination, but they still needed to be able to re-order the required items as desired.
I wanted the Source items to remain sorted after any items were moved into or out of it, and this included drag-n-drop operations. I also wanted the "Transfer All" buttons to work intelligently, so that all items except for the required items were moved accordingly.
While I saw a number of options to prevent the transfer of certain items client-side, there was no client-side sorting mechanism. So I decided to implement everything server-side.
The only real "gotcha" here was implementing the ListBox's "Reordered" event handler. This was necessary because when doing drag-n-drop operations, the ListBox control does an automatic re-ordering of the items in order to drop the item in the exact position you want it. Technically, you're really adding an item to the end of the Items collection, so the re-order happens automatically to place the item where you want it.
In my case, when moving the items from the unsorted ListBox to the sorted ListBox, I had to make sure that the items were sorted AFTER this "Reordered" event fired. Otherwise, the last item in the list after the manual Sort in the "Transferred" even would be moved to wherever the mouse dropped the original item. It was a strange effect, but was solved after asking Telerik about the behavior.
Since it wasn't intuitive to me at first, I thought I'd post the code here for everyone. Hopefully some of you will find it useful.
HTML:
Code-Behind:
Recently I had a requirement in which the users needed to be able to select items from one sorted RadListBox control (Source) and move them to another RadListBox control (Destination). In the Destination box, the users also needed to be able to put the items in any order they wanted. To make matters a little more complicated, the Destination box was pre-populated with some items marked as "required", and the users were not supposed to be able to move those items out of the Destination, but they still needed to be able to re-order the required items as desired.
I wanted the Source items to remain sorted after any items were moved into or out of it, and this included drag-n-drop operations. I also wanted the "Transfer All" buttons to work intelligently, so that all items except for the required items were moved accordingly.
While I saw a number of options to prevent the transfer of certain items client-side, there was no client-side sorting mechanism. So I decided to implement everything server-side.
The only real "gotcha" here was implementing the ListBox's "Reordered" event handler. This was necessary because when doing drag-n-drop operations, the ListBox control does an automatic re-ordering of the items in order to drop the item in the exact position you want it. Technically, you're really adding an item to the end of the Items collection, so the re-order happens automatically to place the item where you want it.
In my case, when moving the items from the unsorted ListBox to the sorted ListBox, I had to make sure that the items were sorted AFTER this "Reordered" event fired. Otherwise, the last item in the list after the manual Sort in the "Transferred" even would be moved to wherever the mouse dropped the original item. It was a strange effect, but was solved after asking Telerik about the behavior.
Since it wasn't intuitive to me at first, I thought I'd post the code here for everyone. Hopefully some of you will find it useful.
HTML:
<
asp:Content
ID
=
"BodyContent"
runat
=
"server"
ContentPlaceHolderID
=
"MainContent"
>
<
telerik:RadScriptManager
ID
=
"RadScriptManager1"
runat
=
"server"
>
</
telerik:RadScriptManager
>
<
telerik:RadAjaxManager
ID
=
"RadAjaxManager1"
runat
=
"server"
>
<
AjaxSettings
>
<
telerik:AjaxSetting
AjaxControlID
=
"RadListBox1"
>
<
UpdatedControls
>
<
telerik:AjaxUpdatedControl
ControlID
=
"RadListBox2"
UpdatePanelCssClass
=
""
/>
</
UpdatedControls
>
</
telerik:AjaxSetting
>
<
telerik:AjaxSetting
AjaxControlID
=
"RadListBox2"
>
<
UpdatedControls
>
<
telerik:AjaxUpdatedControl
ControlID
=
"RadListBox1"
UpdatePanelCssClass
=
""
/>
</
UpdatedControls
>
</
telerik:AjaxSetting
>
</
AjaxSettings
>
</
telerik:RadAjaxManager
>
<
table
>
<
tr
>
<
td
>
<
telerik:RadListBox
ID
=
"RadListBox1"
runat
=
"server"
AllowTransfer
=
"True"
TransferToID
=
"RadListBox2"
SelectionMode
=
"Multiple"
AutoPostBackOnTransfer
=
"true"
Width
=
"300px"
Height
=
"300px"
EnableDragAndDrop
=
"true"
>
<
ButtonSettings
TransferButtons
=
"All"
></
ButtonSettings
>
<
Items
>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem1"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem2"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem3"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem4"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem5"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem6"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem7"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem8"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RadListBoxItem9"
/>
</
Items
>
</
telerik:RadListBox
>
</
td
>
<
td
>
<
telerik:RadListBox
ID
=
"RadListBox2"
runat
=
"server"
SelectionMode
=
"Multiple"
AllowReorder
=
"true"
EnableDragAndDrop
=
"true"
Width
=
"300px"
Height
=
"300px"
>
<
Items
>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RequiredItem1 (required)"
/>
<
telerik:RadListBoxItem
runat
=
"server"
Text
=
"RequiredItem2 (required)"
/>
</
Items
>
</
telerik:RadListBox
>
</
td
>
</
tr
>
</
table
>
</
asp:Content
>
Code-Behind:
private
const
string
REQUIRED_FLAG =
"(required)"
;
protected
void
Page_Init(
object
sender, EventArgs e)
{
RadListBox1.Transferred +=
new
Telerik.Web.UI.RadListBoxTransferredEventHandler(RadListBox1_Transferred);
RadListBox1.Transferring +=
new
Telerik.Web.UI.RadListBoxTransferringEventHandler(RadListBox1_Transferring);
RadListBox1.Reordered +=
new
RadListBoxEventHandler(RadListBox1_Reordered);
}
protected
void
Page_Load(
object
sender, EventArgs e)
{
}
void
RadListBox1_Transferred(
object
sender, Telerik.Web.UI.RadListBoxTransferredEventArgs e)
{
RadListBox1.Sort = Telerik.Web.UI.RadListBoxSort.Ascending;
RadListBox1.SortItems();
}
void
RadListBox1_Transferring(
object
sender, Telerik.Web.UI.RadListBoxTransferringEventArgs e)
{
Boolean transferFail =
false
;
foreach
(RadListBoxItem item
in
e.Items)
{
if
(item.Text.EndsWith(REQUIRED_FLAG))
{
transferFail =
true
;
break
;
}
}
// only do special processing if required fields are in e.Items
// otherwise, let the Transferring and Transferred events fire normally
if
(transferFail)
{
// cancel the event
// (this also prevents the Transferred event from firing after)
e.Cancel =
true
;
foreach
(RadListBoxItem item
in
e.Items)
{
if
(!item.Text.EndsWith(REQUIRED_FLAG))
{
//e.SourceListBox.Transfer(item,e.SourceListBox,e.DestinationListBox);
e.SourceListBox.Items.Remove(item);
e.DestinationListBox.Items.Add(item);
}
}
// Since the Transferred event doesn't fire, sort items
e.DestinationListBox.Sort = RadListBoxSort.Ascending;
e.DestinationListBox.SortItems();
}
}
void
RadListBox1_Reordered(
object
sender, RadListBoxEventArgs e)
{
// Needed to sort AFTER the automatic reordering that Telerik does during the drag-n-drop action
RadListBox1.Sort = Telerik.Web.UI.RadListBoxSort.Ascending;
RadListBox1.SortItems();
}