Click here to Skip to main content
14,366,234 members


Rate this:
4.13 (18 votes)
Please Sign up or sign in to vote.
4.13 (18 votes)
9 Jun 2004CPOL
Two listboxes to choose from and client-side scripting to move items from left to right and vice versa

Image 1


When working with internet-programs, you should reduce the number of post backs to the server to a minimum. This is an often heard sentence. When I was working on a site where I had a lot of these picklists on screen (see screenshot above) which can move items from the left to the right listbox and vice versa. I was in a hurry and didn't want to listen to the message of this sentence. So I made a user-control and some necessary events to be hooked upon in my code-behind. You can imagine that the client response was not so great. Now that I have more time to think it over, I came up with this custom control with client-side scripting that should have worked perfect for that site. But alas, the site is up-and-running so think of this as some fun to please you and me.

Using the code

Picklist is a composite control, which consists of two ListBoxes and four HtmlInputButtons. I tried to name everything as common as possible. So, there is no 'Selected'-listbox or a 'DeSelectAll'-function but a left- and right listbox. I used HtmlInputButtons for these can easilly have JavaScript connected to it.

The class PickList is inherited from webcontrol. It implements the INamingContainer and IPostBackDataHandler. I choose for the WebControl and not for the Control class because it has some webcontrol properties like Height and Width for the layout of the listboxes. The INamingContainer makes the naming of multiple picklists on a webform unique. The first PickList gets a name like PickList1, the second one gets PickList2. The IPostBackDataHandler is nessecary for getting values back out of some hidden fields which are being filled by JavaScript on the client. Getting values back on the server is done in the LoadPostData method. Through the PostCollection collection, the posted-back-values can be retrieved. It seems to me that this collection contains the same as the Page.Request.Forms collection.

The working of PickList is that you fill the listboxes with whatever you want during design-time or in code. When rendering the control to html, it saves the items from the listboxes separated with <tab>'s to viewstate which is done in the Page_Load method. This way, we know what was originally in the listboxes when we get a postback. Next, in the OnPreRender function, we render two hiddenfields to the client, which are later being filled by JavaScript on the client. In the beginning when making this control, I used two HtmlInputHidden controls for storing values. I had to create these two controls in the CreateChildControls, set there ID's and values and then add these to the controls collection. After searching the internet I coincidentally found the Page.RegisterHiddenField function which works the Microsoft way and is used now, instead of the HtmlInputHidden controls. Since this function, there is no need for setting the values and add it to the controls-collection. Ironically, the work saved, is not significant.

protected override void OnPreRender(EventArgs e)
        if (Page != null)
        Page.RegisterHiddenField(HelperLeftID, this.ValuesLeft);
        Page.RegisterHiddenField(HelperRightID, this.ValuesRight);

On the client, the JavaScript moves the items from one listbox to the other when the user clicks a HtmlInputButton. After this move, it sorts the collection whenever the IsSorted property is set to true. Hereafter, another JavaScript function will copy the items in the listboxes, separated with <tab>'s, to the two hiddenfields which are being read on the server when a postback takes place.

When the postback take place, the two hidden fields contain the new values for the listboxes. In the IPostBackDataHandler.LoadPostData method, the values are being read from the postCollection and compared to the saved viewstate. When changed, the items are stored in the item-collection of the listboxes. The new viewstate value's can also be saved here, but it better be saved in the Page_Load method. It seems that the collection has to be read again in the Page_Load, and it does. So why do this twice? Because the first time the control is created, the LoadPostData does not fire, but Page_Load will. ViewState has to be set for the control to work properly.

bool IPostBackDataHandler.LoadPostData(string postDataKey,
    System.Collections.Specialized.NameValueCollection postCollection)
    bool lblnReturn = false; 
    string NewLeftValue = postCollection[HelperLeftID]; 
    string NewRightValue = postCollection[HelperRightID];
    if (NewLeftValue != null) 
        // If the user changes Input value, update the text property. 
        if (String.Compare(this.ValuesLeft, NewLeftValue) != 0) 
            foreach (string str in NewLeftValue.Split(strSep)) 
                if (str != string.Empty) 
                // Here ViewState could easilly be set 
                // Something like: this.ValuesLeft += str
            // Returning true invokes RaisePostDataChangedEvent. 
            lblnReturn = true; 
    return lblnReturn;

Consider when calling Page.RegisterClientScriptBlock , always first call Page.IsClientSideScriptBlockRegistered , which will avoid the performance taking call to <CODE>Page.RegisterClientScriptBlock like this:

if (!Page.IsClientScriptBlockRegistered("PickListScript"))
        Page.RegisterClientScriptBlock("PickListScript", script);

This way, what is done in code behind for making the script is omitted.

In the source of the control, JavaScript is set in code-behind. I could have chosen for a separate js-file, but I choose for better deployment. Also, by reading the property IsSorted, the sort-function from the JavaScript can be switched off. When using a separate js-file should be some more coding.

Points of Interest

Databinding is not supported in this control because of simplicity. However, you can extent this control with databinding features from this good article I have done it and it works great.

Also I thought it was difficult to implement child ListItems in the html-code like so:

<PickList id="PickList1">
    <LeftListBox ID="left1">
        <asp:ListItem Value="1">one</asp:ListItem>
            <asp:ListItem Value="1">one</asp:ListItem>

The solution was found at I should have entered the ParseChildren(true) and PersistChildrenattribute(false).

Also to view the ListBox in design-time properly, set the height and width property to something like 150px. I did not support a designer-class for design-time support. The look and feel in design-time comes directly from the Render method.

Hope you enjoyed it!


  • Version 1.0, June 2004.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer
Netherlands Netherlands
Hi my name is Dries de Groot. I have a Masters degree in applied physics and am graduated in solid-state matter. Besides that I am a .NET Professional with scrum certificates

Comments and Discussions

QuestionNeed to implement hierarchy in PickList control Pin
kgoyal19-Dec-11 12:44
memberkgoyal19-Dec-11 12:44 
AnswerRe: Need to implement hierarchy in PickList control Pin
3sL23-Dec-11 4:27
member3sL23-Dec-11 4:27 
GeneralSmall fix for VB users Pin
MyCodeProject200521-Aug-09 1:18
memberMyCodeProject200521-Aug-09 1:18 
GeneralNice! Pin
JasonC7213-Oct-08 6:23
memberJasonC7213-Oct-08 6:23 
QuestionFacing LIstBox Problem Pin
sinhasourabh6-Jul-08 4:27
groupsinhasourabh6-Jul-08 4:27 
GeneralUpdation in problem Pin
sinhasourabh6-Jul-08 4:31
groupsinhasourabh6-Jul-08 4:31 
GeneralTwo List Boxes in using C# Pin
Manikkuttan10-Jun-08 20:18
memberManikkuttan10-Jun-08 20:18 
GeneralBUG Report Pin
CDSGIO7312-Sep-07 1:03
memberCDSGIO7312-Sep-07 1:03 
GeneralData mismatch after postback Pin
jyothiraj24-Jan-07 19:01
memberjyothiraj24-Jan-07 19:01 
GeneralMy component won't let me declare a LoadPostData Function Pin
howardjr19-Dec-06 18:34
memberhowardjr19-Dec-06 18:34 
GeneralRe: My component won't let me declare a LoadPostData Function Pin
Sebastian Streiger20-Dec-06 7:06
memberSebastian Streiger20-Dec-06 7:06 
GeneralRe: My component won't let me declare a LoadPostData Function Pin
howardjr20-Dec-06 8:31
memberhowardjr20-Dec-06 8:31 
GeneralRe: My component won't let me declare a LoadPostData Function Pin
Sebastian Streiger20-Dec-06 10:55
memberSebastian Streiger20-Dec-06 10:55 
GeneralRe: My component won't let me declare a LoadPostData Function Pin
howardjr20-Dec-06 11:26
memberhowardjr20-Dec-06 11:26 
GeneralRe: My component won't let me declare a LoadPostData Function Pin
Sebastian Streiger21-Dec-06 2:35
memberSebastian Streiger21-Dec-06 2:35 
GeneralRe: My component won't let me declare a LoadPostData Function Pin
howardjr21-Dec-06 12:33
memberhowardjr21-Dec-06 12:33 
Generaladd ondblclick Pin
xiezhenhua14-Nov-06 19:27
memberxiezhenhua14-Nov-06 19:27 
GeneralRe: add ondblclick Pin
3sL18-Nov-06 10:18
member3sL18-Nov-06 10:18 
GeneralThanks for the article. Pin
Lakshmipathy21-Sep-06 21:15
memberLakshmipathy21-Sep-06 21:15 
GeneralRe: Thanks for the article. Pin
3sL18-Nov-06 10:18
member3sL18-Nov-06 10:18 
QuestionHaving problem when used with master page Pin
jagamagge18-Aug-06 0:57
memberjagamagge18-Aug-06 0:57 
AnswerRe: Having problem when used with master page Pin
3sL18-Nov-06 10:21
member3sL18-Nov-06 10:21 
GeneralStyle Attributes Pin
groovq27-Jul-06 20:53
membergroovq27-Jul-06 20:53 
GeneralRe: Style Attributes Pin
3sL30-Aug-06 22:02
member3sL30-Aug-06 22:02 
QuestionHow Do i Add display text and values? Pin
pgarbutt9-Dec-05 11:11
memberpgarbutt9-Dec-05 11:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Posted 7 Jun 2004


75 bookmarked