Moving Sorting Searching and Filtering Items between ListBoxes User Control






4.44/5 (6 votes)
How to move, sort, filter and search items between Listboxes and make it as reusable user control using ASP.NET (C#)
Introduction
In this example, I will explain how to do searching, filtering, sorting and moving the items between two ListBox
es and make it a reusable user control using Generic Collection IList
in ASP.NET (C#).
Generic collection
is used to bind the ListBox
es with any Generic type IList
and also explain how to bind both ListBox
es and remove all the existing records from the Source Listbox
which already exists in Destination Listbox
if in case you need to update the existing records which are already saved in database.
Background
Almost all web applications have security module to gives grants and privileges to the users. In this scenario, developers require two Listbox
es for available permissions and granting permission. They need lots of effort to develop the functionality every time in their application.
Source Code
In the first part, explain how to develop the user control using two ListBox
es and add the functionality of these two ListBox
es. After that, we will add the user control in a page and call it .
User Control Code
- Create a new website in .NET 2008 and add the user control from add new item from the solution. Name it
ucListBox
.
ASCX Code
<%@ Control Language="C#" AutoEventWireup="false"
CodeBehind="ucListBox.ascx.cs" Inherits="ListBox_Demo.ucListBox" %>
<script type="text/javascript" language="javascript">
var ddlText, ddlValue, ddl, lblMesg;
function CacheItems() {
ddlText = new Array();
ddlValue = new Array();
ddl = document.getElementById("<%=lstAvailable.ClientID %>");
for (var i = 0; i < ddl.options.length; i++) {
ddlText[ddlText.length] = ddl.options[i].text;
ddlValue[ddlValue.length] = ddl.options[i].value;
}
}
window.onload = CacheItems;
function FilterItems(value) {
ddl.options.length = 0;
for (var i = 0; i < ddlText.length; i++) {
if (ddlText[i].toLowerCase().indexOf(value) != -1) {
AddItem(ddlText[i], ddlValue[i]);
}
}
if (ddl.options.length == 0) {
AddItem("", "");
}
}
function AddItem(text, value) {
var opt = document.createElement("option");
opt.text = text;
opt.value = value;
ddl = document.getElementById("<%=lstAvailable.ClientID %>");
ddl.options.add(opt);
}
</script>
<table width="100%" border="0" id="tblSearch" runat="server" visible="true">
<tr>
<td style="width: 19%; height: 24px;" align="left" runat="server" id="tdd">
<span style="font-size: 8pt"><strong>
<asp:Label runat="server" Text="Search" ID="lblSearch"></asp:Label>
</strong></span>
</td>
<td>
<asp:TextBox ID="txtSearch" runat="server"
onkeyup="FilterItems(this.value)"></asp:TextBox><br />
</td>
</tr>
</table>
<table width="80%" border="0">
<tr align="left">
<td align="left">
<!-- Start list box-->
<table width="100%">
<tr>
<td valign="top">
<table border="0" width="100%">
<tr>
<td>
<span style="font-size: 8pt"><strong>
<asp:Label runat="server"
ID="lblAvailable" Text="Available"></asp:Label>
</strong></span>
</td>
</tr>
<tr>
<td style="height: 200px">
<asp:ListBox ID="lstAvailable"
runat="server" Height="100%" SelectionMode="Multiple"
Width="300px" Font-Size="10pt"></asp:ListBox>
</td>
</tr>
</table>
</td>
<td align="center" valign="top">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<br />
</td>
</tr>
<tr>
<td>
<br />
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>
<asp:ImageButton ID="btnAddAll"
ImageUrl="~/Images/GrantAll.png"
runat="server" CausesValidation="False" />
</td>
</tr>
<tr>
<td>
<asp:ImageButton ID="btnAdd"
ImageUrl="~/Images/Grant.png"
runat="server" CausesValidation="False" />
</td>
</tr>
<tr>
<td>
<asp:ImageButton ID="btnRemove"
ImageUrl="~/Images/Revoke.png"
runat="server" CausesValidation="False" />
</td>
</tr>
<tr>
<td>
<asp:ImageButton ID="btnRemoveAll"
ImageUrl="~/Images/RevokeAll.png" runat="server"
CausesValidation="False" />
</td>
</tr>
</table>
</td>
<td valign="top">
<table width="100%">
<tr>
<td>
<span style="font-size: 8pt"><strong>
<asp:Label runat="server"
ID="lblAdded" Text="Added"></asp:Label>
</strong></span>
</td>
</tr>
<tr>
<td style="height: 200px">
<asp:ListBox ID="lstAdded"
runat="server" Font-Size="10pt"
Height="100%" SelectionMode="Multiple"
Width="300px"></asp:ListBox>
</td>
</tr>
<tr>
<td>
</td>
</tr>
</table>
</td>
<td>
<table width="100%">
<tr>
<td>
<asp:ImageButton ID="btnMoveUp"
runat="server" ImageUrl="~/Images/MoveUp.png"
CausesValidation="False" />
</td>
</tr>
<tr>
<td>
<asp:ImageButton ID="btnMoveDown"
runat="server" CausesValidation="False"
ImageUrl="~/Images/MoveDown.png" />
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- end list box-->
</td>
</tr>
</table>
In the above code, I added one label and text box for searching and filtering the records in the available ListBox
called lstAvailable.
I have used two listbox
es - lstAvailable
and lstAdded
, Move, Next, Pervious, First, Up and Down buttons for moving and sorting the items between the ListBox
es.
The above three JavaScript methods take care of the Filtering and Searching process. The details of these methods is described below:
CacheItems
This method is called on the window onload
event. The job of this method is to populate text and value arrays that will be used to cache the ListBox
items of Available List.
FilterItems
This method is called when keyup
event fires in the Search TextBox. This method searches for the string
segment and filters the ListBox
items of Available List.
AddItem
This method is used to add a new item in the ListBox
.
C# Code
Add the System.Collections
in code behind and add the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
namespace ListBox_Demo
{
public partial class ucListBox : System.Web.UI.UserControl
{
#region Property
private IList _DataSourceAvailable = null;
private IList _DataSourceAdded = null;
private string _dataTextFieldAvailable = string.Empty;
private string _dataValueFieldAvailable = string.Empty;
private string _dataTextFieldAdded = string.Empty;
private string _dataValueFieldAdded = string.Empty;
private string _availableItemText = "Available Roles"; //Resources.Common.AvailableItemText;
private string _addedItemText = "Assgin Roles";// Resources.Common.AddedItemText;
protected ArrayList arlList = new ArrayList();
/// <summary>
/// Gets or sets the available item text.
/// </summary>
/// <value>The available item text.</value>
public string AvailableItemHeaderText
{
get { return _availableItemText; }
set { _availableItemText = value; }
}
/// <summary>
/// Gets or sets the added items text.
/// </summary>
/// <value>The added items text.</value>
public string AddedItemsHeaderText
{
get { return _addedItemText; }
set { _addedItemText = value; }
}
/// <summary>
/// Gets the available items.
/// </summary>
/// <value>The available items.</value>
public ListItemCollection AvailableItems
{
get { return lstAvailable.Items; }
}
/// <summary>
/// Gets the added items.
/// </summary>
/// <value>The added items.</value>
public ListItemCollection AddedItems
{
get { return lstAdded.Items; }
}
/// <summary>
/// Gets or sets the data source for the available items listbox.
/// </summary>
/// <value>The data source for available items.</value>
public IList DataSourceAvailable
{
get { return _DataSourceAvailable; }
set { _DataSourceAvailable = value; }
}
/// <summary>
/// Gets or sets the data source for the added items listbox.
/// </summary>
/// <value>The data source for added items.</value>
public IList DataSourceAdded
{
get { return _DataSourceAdded; }
set { _DataSourceAdded = value; }
}
/// <summary>
/// Gets or sets the data text field available.
/// </summary>
/// <value>The data text field available.</value>
public string DataTextFieldAvailable
{
get { return _dataTextFieldAvailable; }
set { _dataTextFieldAvailable = value; }
}
/// <summary>
/// Gets or sets the data value field available.
/// </summary>
/// <value>The data value field available.</value>
public string DataValueFieldAvailable
{
get { return _dataValueFieldAvailable; }
set { _dataValueFieldAvailable = value; }
}
/// <summary>
/// Gets or sets the data text field added.
/// </summary>
/// <value>The data text field added.</value>
public string DataTextFieldAdded
{
get { return _dataTextFieldAdded; }
set { _dataTextFieldAdded = value; }
}
/// <summary>
/// Gets or sets the data value field added.
/// </summary>
/// <value>The data value field added.</value>
public string DataValueFieldAdded
{
get { return _dataValueFieldAdded; }
set { _dataValueFieldAdded = value; }
}
#endregion
#region Method
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Initializer();
}
private void Initializer()
{
btnAdd.Click += new ImageClickEventHandler(btnAdd_Click);
btnAddAll.Click += new ImageClickEventHandler(btnAddAll_Click);
btnRemove.Click += new ImageClickEventHandler(btnRemove_Click);
btnRemoveAll.Click += new ImageClickEventHandler(btnRemoveAll_Click);
btnMoveUp.Click += new ImageClickEventHandler(btnMoveUp_Click);
btnMoveDown.Click += new ImageClickEventHandler(btnMoveDown_Click);
//lblAdded.Text = this.AddedItemsHeaderText;
//lblAvailable.Text = this.AvailableItemHeaderText;
}
public void BindAvailableList()
{
//Set the Header Text of the Available and Added Items
lblAdded.Text = this.AddedItemsHeaderText;
lblAvailable.Text = this.AvailableItemHeaderText;
//Bind the Added List Control
lstAvailable.DataSource = this.DataSourceAvailable;
lstAvailable.DataTextField = this.DataTextFieldAvailable;
lstAvailable.DataValueField = this.DataValueFieldAvailable;
lstAvailable.DataBind();
}
public void BindAddedList()
{
//Set the Header Text of the Available and Added Items
lblAdded.Text = this.AddedItemsHeaderText;
lblAvailable.Text = this.AvailableItemHeaderText;
//Bind the Available List Control
lstAdded.DataSource = this.DataSourceAdded;
lstAdded.DataTextField = this.DataTextFieldAdded;
lstAdded.DataValueField = this.DataValueFieldAdded;
lstAdded.DataBind();
}
public void BindList()
{
//Set the Header Text of the Available and Added Items
lblAdded.Text = this.AddedItemsHeaderText;
lblAvailable.Text = this.AvailableItemHeaderText;
//Bind the Available and Added List Controls
lstAdded.DataSource = this.DataSourceAdded;
lstAdded.DataTextField = this.DataTextFieldAdded;
lstAdded.DataValueField = this.DataValueFieldAdded;
lstAdded.DataBind();
lstAvailable.DataSource = this.DataSourceAvailable;
lstAvailable.DataTextField = this.DataTextFieldAvailable;
lstAvailable.DataValueField = this.DataValueFieldAvailable;
lstAvailable.DataBind();
#region Remove intersection Record
ArrayList ary = new ArrayList();
for (int i = 0; i < lstAvailable.Items.Count; i++)
{
for (int j = 0; j < lstAdded.Items.Count; j++)
{
if (lstAvailable.Items[i].Value == lstAdded.Items[j].Value)
{
// lstAvailable.RemoveAt(i);
if (!ary.Contains(lstAvailable.Items[i]))
{
ary.Add(lstAvailable.Items[i]);
j = -1;
}
break;
}
}
}
for (int i = 0; i < ary.Count; i++)
{
lstAvailable.Items.Remove(((ListItem)ary[i]));
}
#endregion
ScriptManager.RegisterStartupScript(this.Page, typeof(Page), "myscript", "CacheItems();", true);
//ScriptManager.RegisterStartupScript(Page, typeof(Page), "myscript", "UploadFileToParent();", true);
}
#endregion
#region Navigation
/// <summary>
/// Add all the selected items from the Available Items to the Added Items
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/>
/// instance containing the event data.</param>
protected void btnAdd_Click(object sender, EventArgs e)
{
if (lstAvailable.SelectedIndex >= 0)
{
for (int i = 0; i < lstAvailable.Items.Count; i++)
{
if (lstAvailable.Items[i].Selected)
{
if (!arlList.Contains(lstAvailable.Items[i]))
arlList.Add(lstAvailable.Items[i]);
}
}
for (int i = 0; i < arlList.Count; i++)
{
if (!lstAdded.Items.Contains((ListItem)arlList[i]))
lstAdded.Items.Add((ListItem)arlList[i]);
lstAvailable.Items.Remove((ListItem)arlList[i]);
}
}
}
/// <summary>
/// Add all the items from the Available items to the Added Items
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="
/// System.EventArgs"/> instance containing the event data.</param>
protected void btnAddAll_Click(object sender, EventArgs e)
{
foreach (ListItem list in lstAvailable.Items)
{
lstAdded.Items.Add(list);
}
lstAvailable.Items.Clear();
}
/// <summary>
/// Moves the Selected items from the Added items to the Available items
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="
/// System.EventArgs"/> instance containing the event data.</param>
protected void btnRemove_Click(object sender, EventArgs e)
{
if (lstAdded.SelectedIndex >= 0)
{
for (int i = 0; i < lstAdded.Items.Count; i++)
{
if (lstAdded.Items[i].Selected)
{
if (!arlList.Contains(lstAdded.Items[i]))
arlList.Add(lstAdded.Items[i]);
}
}
for (int i = 0; i < arlList.Count; i++)
{
if (!lstAvailable.Items.Contains((ListItem)arlList[i]))
lstAvailable.Items.Add((ListItem)arlList[i]);
lstAdded.Items.Remove((ListItem)arlList[i]);
}
}
}
/// <summary>
/// Moves all the items from the Added items to the Available items
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">
/// The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void btnRemoveAll_Click(object sender, EventArgs e)
{
foreach (ListItem list in lstAdded.Items)
{
lstAvailable.Items.Add(list);
}
lstAdded.Items.Clear();
}
/// <summary>
/// Move item to upwards
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void btnMoveDown_Click(object sender, ImageClickEventArgs e)
{
try
{
int startindex = lstAdded.Items.Count - 1;
for (int i = startindex; i > -1; i--)
{
if (lstAdded.Items[i].Selected)//identify the selected item
{
//swap with the lower item(move down)
if (i < startindex && !lstAdded.Items[i + 1].Selected)
{
ListItem bottom = lstAdded.Items[i];
lstAdded.Items.Remove(bottom);
lstAdded.Items.Insert(i + 1, bottom);
lstAdded.Items[i + 1].Selected = true;
}
}
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// Move Item To down Words
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void btnMoveUp_Click(object sender, ImageClickEventArgs e)
{
try
{
for (int i = 0; i < lstAdded.Items.Count; i++)
{
if (lstAdded.Items[i].Selected)//identify the selected item
{
//swap with the top item(move up)
if (i > 0 && !lstAdded.Items[i - 1].Selected)
{
ListItem bottom = lstAdded.Items[i];
lstAdded.Items.Remove(bottom);
lstAdded.Items.Insert(i - 1, bottom);
lstAdded.Items[i - 1].Selected = true;
}
}
}
}
catch (Exception ex)
{
}
}
#endregion
}
}
The above mentioned three binds functions are used to bind ListBox
and each one has a different functionality whose description is given below.
BindAvailableList()
If you want to bind the Available ListBox
, then call this method form the aspx page and its required following properties should be assigned from the aspx page:
DataSourceAvailable
: Pass theIList
CollectionDataTextFieldAvailable
: Its required Property Name which shows in theListBox
DataValueFieldAvailable
: Its required Property ID which should be unique in theListBox
BindAddedList()
If you want to bind the Added ListBox
, then call this method form the aspx page and its required following properties should be assign from the aspx page.
DataSourceAdded
: Pass theIList
CollectionDataTextFieldAdded
: Its required Property Name which shows in theListBox
DataValueFieldAdded
: Its required Property ID which should be unique in theListBox
BindList()
If you want to bind both ListBox
es Available
and Added
and need to remove all the items which already exist in the Added ListBox
, then call this function from the aspx page and its required following properties should be assigned from the aspx page.
DataSourceAvailable
: Pass theIList
CollectionDataTextFieldAvailable
: Its required Property Name which shows in theListBox
DataValueFieldAvailable
: Its required Property ID which should be unique in theListBox
DataSourceAdded
: Pass theIList
CollectionDataTextFieldAdded
: Its required Property Name which shows in theListBox
DataValueFieldAdded
: ItsListBox
Note
AvailableItemHeaderText
and AddedItemsHeaderText
are optional, It will be required if you want to change the heading of Listbox
es from aspx page.
GUI Page Code
Aspx Code
Add the ucListBox
user control in default.aspx page which is automatically added in the website when you created it in .NET 2008.
<%@ Register src="ucListBox.ascx" tagname="ucListBox" tagprefix="uc1" %>
To show the complete working of user control, I have created three buttons in a page and call user control all three binds methods.
<%@ Page Language="C#" AutoEventWireup="false" CodeBehind="Default.aspx.cs" Inherits="ListBox_Demo._Default" %>
<%@ Register src="ucListBox.ascx" tagname="ucListBox" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAvailable" runat="server" Text="Bind Available List"
onclick="btnAvailable_Click" />
<asp:Button ID="btnAdded" runat="server" Text="Bind Added List"
onclick="btnAdded_Click" />
<asp:Button ID="btnBoth" runat="server" Text="Bind Both"
onclick="btnBoth_Click" />
<uc1:ucListBox ID="ucListBox1" runat="server" />
</div>
</form>
</body>
</html>
C# Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
namespace ListBox_Demo
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
void AvailableItems()
{
List<Roles> lstRole = new List<Roles>();
Roles objRoles = new Roles();
objRoles.ID = 1;
objRoles.Name = "Admin";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 2;
objRoles.Name = "Manager";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 3;
objRoles.Name = "Supervisor";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 4;
objRoles.Name = "Employee";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 5;
objRoles.Name = "User";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 6;
objRoles.Name = "Client";
lstRole.Add(objRoles);
ucListBox1.DataTextFieldAvailable = "Name";
ucListBox1.DataValueFieldAvailable = "ID";
ucListBox1.DataSourceAvailable = lstRole;
ucListBox1.AvailableItemHeaderText = "Available Permissions";
ucListBox1.AddedItemsHeaderText = "Added Permissions";
}
void SelectedItems()
{
List<Roles> lstRole = new List<Roles>();
Roles objRoles = new Roles();
objRoles.ID = 1;
objRoles.Name = "Admin";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 2;
objRoles.Name = "Manager";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 4;
objRoles.Name = "Employee";
lstRole.Add(objRoles);
objRoles = new Roles();
objRoles.ID = 5;
objRoles.Name = "User";
lstRole.Add(objRoles);
ucListBox1.DataTextFieldAdded = "Name";
ucListBox1.DataValueFieldAdded = "ID";
ucListBox1.DataSourceAdded = lstRole;
ucListBox1.AvailableItemHeaderText = "Available Permissions";
ucListBox1.AddedItemsHeaderText = "Added Permissions";
}
protected void btnAvailable_Click(object sender, EventArgs e)
{
AvailableItems();
ucListBox1.BindAvailableList();
}
protected void btnAdded_Click(object sender, EventArgs e)
{
SelectedItems();
ucListBox1.BindAddedList();
}
protected void btnBoth_Click(object sender, EventArgs e)
{
AvailableItems();
SelectedItems();
ucListBox1.BindList();
}
}
public class Roles
{
public int ID { get; set; }
public string Name { get; set; }
}
}
I have created two functions, SelectedItems()
and AvailableItems()
to fill the hard code List and call it on three different button clicks.
Points of Interest
It was annoying writing these examples since they are too big and took up a lot of my time.