Moving items between listboxes in ASP.net/PHP example

June 12, 2008 by Christoff Truter JavaScript   PHP   ASP.NET   Visual Basic  

Ever wanted to move items between two listboxes in ASP.net (or PHP for that matter)?



Someone wanted the exact same thing on codeproject.com a while ago but I didn't give much thought to it, until someone at work asked me how to do it - since he wasn't able to find a viable solution on the internet.

The solution I scripted wasn't as simple as I thought, nor would have liked it to be, my feeling was that one would be able to alter the two listboxes easily using javascript and simply "harvest" the changes (from the Request variables) when its submitted to the server.

The reality however is that only items selected(or highlighted) in the listboxes, will be returned to the server, not the state of the listboxes - so we need to somehow send the state of the listboxes along with the page request.

What I did was, I wrote a javascript script, that serialized the contents of the listboxes as xml to a hiddenfield on the page - whenever you submit the form to the server, a xml string containing the state of the listboxes get sent along - which one can easily process server side (which I will show you just in a while).

function move(fromID, toID, containerID)
{
    var from = document.getElementById(fromID);
    var to = document.getElementById(toID);

    for (var i = 0; i < from.options.length; i++)
    {
        if (from.options[i].selected)
        {					
            to.options.add(new Option(from.options[i].text,from.options[i].value))
            from.remove(i--);
        }
    }

    var container = document.getElementById(containerID);	
    container.value = escape("<listboxes>" + serialize(from) + serialize(to) + "</listboxes>");
}

function serialize(dropdown)
{	
    var value = '<' + dropdown.id + '>';	
    for (var i = 0; i < dropdown.options.length; i++)
    {
        value+= '<option><key><![CDATA[' + encodeURIComponent(dropdown.options[i].text) + ']]></key><value><![CDATA[' + encodeURIComponent(dropdown.options[i].value) + ']]></value></option>';
    }
    value+='</' + dropdown.id + '>';
    return value
}

function unselect(listbox)
{
    document.getElementById(listbox).selectedIndex=-1;
}


Tying it all together (javascript with some .net code), you can easily write yourself an usercontrol, like I did in my example, or create a composite control.

The .net code below is pretty straighforward, you'll noticed two publicly exposed ListBox properties (lstFrom, lstTo), giving us easy access to the listboxes.

If you really need to, you can easily add third, forth listboxes (with slight changes to the javascript code)

The PHP code is quite a bit more involved, I had to create a few classes that give similiar control of what you would expect from an ASP.NET server side control. There is a lot easier ways to do this, but I believe this is a fairly manageable approach.

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

public partial class ListPicker : System.Web.UI.UserControl
{
    private XmlDocument _xmlDocument = new XmlDocument();

    public ListBox fromListBox
    {
        get
        {
            return lstFrom;
        }
    }

    public ListBox toListBox
    {
        get
        {
            return lstTo;
        }
    }

    private void PopulateListBox(ListBox listBox)
    {
        listBox.Items.Clear();
        XmlNodeList nodes = _xmlDocument.SelectNodes("listboxes/" + listBox.ClientID + "/option");
        foreach (XmlNode node in nodes)
        {
            listBox.Items.Add(new ListItem(HttpUtility.UrlDecode(node["key"].InnerText), HttpUtility.UrlDecode(node["value"].InnerText)));
        }
    }

    private void PopulateListBoxes()
    {        
        _xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdowns.Value));
        PopulateListBox(lstFrom);
        PopulateListBox(lstTo);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        Page.ClientScript.RegisterClientScriptInclude("listboxjs", Page.ResolveClientUrl("~/js/listbox.js"));
        if (!IsPostBack)
        {
            String movejs = "move('{0}','{1}','{2}')";
            String unselectjs = "unselect('{0}')";
            lstFrom.Attributes["onclick"] = String.Format(unselectjs, lstTo.ClientID);
            lstTo.Attributes["onclick"] = String.Format(unselectjs, lstFrom.ClientID);
            btnTo.Attributes["onclick"] = String.Format(movejs, lstFrom.ClientID, lstTo.ClientID, hdnDropdowns.ClientID);
            btnFrom.Attributes["onclick"] = String.Format(movejs, lstTo.ClientID, lstFrom.ClientID, hdnDropdowns.ClientID);
        }
        else
        {
            if (!(String.IsNullOrEmpty(hdnDropdowns.Value)))
            {
                PopulateListBoxes();
            }
        }
    }
}
Imports System.Xml

Partial Class ListPicker
    Inherits System.Web.UI.UserControl

    Private _xmlDocument As New XmlDocument()

    Public ReadOnly Property fromListBox() As ListBox
        Get
            Return lstFrom
        End Get
    End Property

    Public ReadOnly Property toListBox() As ListBox
        Get
            Return lstTo
        End Get
    End Property

    Private Sub PopulateListBox(ByVal lstBox As ListBox)
        lstBox.Items.Clear()
        Dim nodes As XmlNodeList = _xmlDocument.SelectNodes("listboxes/" + lstBox.ClientID + "/option")
        For Each node As XmlNode In nodes
            lstBox.Items.Add(New ListItem(HttpUtility.UrlDecode(node.Item("key").InnerText), HttpUtility.UrlDecode(node.Item("value").InnerText)))
        Next
    End Sub

    Private Sub PopulateListBoxes()
        _xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdowns.Value))
        PopulateListBox(lstFrom)
        PopulateListBox(lstTo)
    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

Page.ClientScript.RegisterClientScriptInclude("listboxjs", Page.ResolveClientUrl("~/js/listbox.js"))

        If Not IsPostBack Then
            Dim movejs As String = "move('{0}','{1}','{2}')"
            Dim unselectjs As String = "unselect('{0}')"

            lstFrom.Attributes("onclick") = String.Format(unselectjs, lstTo.ClientID)
            lstTo.Attributes("onclick") = String.Format(unselectjs, lstFrom.ClientID)
            btnTo.Attributes("onclick") = String.Format(movejs, lstFrom.ClientID, lstTo.ClientID, hdnDropdowns.ClientID)
            btnFrom.Attributes("onclick") = String.Format(movejs, lstTo.ClientID, lstFrom.ClientID, hdnDropdowns.ClientID)
        Else
            If Not String.IsNullOrEmpty(hdnDropdowns.Value) Then
                PopulateListBoxes()
            End If
        End If
    End Sub
End Class
<?php

require_once("controls.php");
require_once("listbox.php");

class listpicker extends controls
{
    var $lstFrom;
    var $lstTo;
    var $deserializable;

    function listpicker($id)
    {
        $this->attributes['id'] = $id;
        $this->lstFrom = new listbox($id.'_lstFrom');
        $this->lstFrom->attributes['style'] = 'width:200px';
        $this->lstFrom->attributes['onclick'] = "unselect('".$id."_lstTo')";	
        $this->lstTo = new listbox($id.'_lstTo');
        $this->lstTo->attributes['style'] = 'width:200px';
        $this->lstTo->attributes['onclick'] = "unselect('".$id."_lstFrom')";

        if ($_REQUEST[$id.'$hdnDropdowns'])
        {
            $this->deserializable = true;
            $this->xml(urldecode($_REQUEST[$id.'$hdnDropdowns']));			
        }	
    }

    function render()
    {	
    $id = $this->attributes['id'];
    $html='<table>
                <tr>
                    <td>'
                        .$this->lstFrom->render().
                    '</td>
                    <td>
                        <input id="btnTo" type="button" value=">>" onclick="move(\''.$id.'_lstFrom\',\''.$id.'_lstTo\',\''.$id.'_hdnDropdowns\')" />
                            <br />
                        <input id="btnFrom" type="button" value="<<" onclick="move(\''.$id.'_lstTo\',\''.$id.'_lstFrom\',\''.$id.'_hdnDropdowns\')" />
                    </td>
                    <td>'		
                        .$this->lstTo->render().
                    '</td>
                </tr>
            </table>
	        <input type="hidden" ID="'.$id.'_hdnDropdowns" name="'.$id.'$hdnDropdowns" />';		
    return $html;
    }

    function xml($text) 
    {		
        $id = $this->attributes['id'];
        $parser = xml_parser_create();
        xml_parse_into_struct($parser, $text, $vals);
        xml_parser_free($parser);
        $tag = "";

        for($i = 0; $i < count($vals); $i++)
        {	
            switch($vals[$i]['tag'])
            {
                case strtoupper($id.'_lstFrom') : $tag = "lstFrom";	break;
                case strtoupper($id.'_lstTo') : $tag = "lstTo";	break;
            }

            if (($tag) && ($vals[$i]['tag'] == "KEY"))
            {
                $this->{$tag}->addItem($vals[$i]['value'], $vals[$i+1]['value']);					
            }
        }
    }
}

?>


Related Downloads

Moving items between listboxes


Leave a Comment


Getting and updating data from the list August 7, 2013 by Anonymous

Dear, First, thank for your interesting codes. I used the codes to load data from database to the first list and I need your help to store items of the second list to database. How to get these values, I tried with _POST[] but I can't refer to the name of the second one. I look forward to your reply. Regard, Duy

August 2, 2013 by Maya

Hi again, I used: include "includes/listpicker.php"; $picker = new listpicker("picker"); print_r($picker->lstTo); and I got Again Picker = listbox Object ( [items] => Array ( [St. Lucy C.S.] => STLUC [Birchbank P.S.] => BBANK [Arnott Charlton P.S.] => ARNCH [Kingswood Drive P.S.] => KINWD [Treeline P.S.] => TREEL ) [attributes] => Array ( [id] => picker_lstTo [multiple] => multiple [style] => width:200px [onclick] => unselect('picker_lstFrom') ) ) : What I need is to take only the values (STLUC, BBANK, ARNCH, KINWD, TREEL) to insert them in database. I am new in PHP and I don't know how get this values and keep them in variables. thank you Maya

retrieve values of selected August 2, 2013 by Maya

Hi, Thank you for sharing the code, it is very useful for me. Please can anybody tell me how can I get the values of the selected items? In which variables are they stored? I need these variables to save the selected items in database. Thank You in advance Maya

Can you modify the code so that only one element can be transferred. February 28, 2013 by Rohit

Hi Christoff Truter, Your code is great but I have a requirement that would allow a user only to select a single item from listbox(from) and transfer it to listbox(to). Rest all items from listbox(from) cannot be transferred to listbox(to). i.e only one item can be transferred from listbox(from) to listbox(to).

many to one October 17, 2012 by Anonymous

Hi Christoff Truter, I already downloaded your source code. That's very helpful. Thank you so much, Now I want to do some revise about your code. I want in left there are 3 or more listboxs, in right side only one listbox. Item form each listboxs can move to the right one. Can you give me a hint how to do that change? Thank you again

Thanks: Latest Source Code May 8, 2012 by Iva

Christoff, thanks a lot for your care. It's great. Iva

Latest Source Code May 8, 2012 by Christoff Truter

Hi Iva Sorry about the delay, the latest updated source code is now available from http://www.cstruter.com/downloads/download.php?downloadid=5

Re:Invalid Characters May 8, 2012 by Iva

Dear Christoff, could you, please, write me, where is the difference of changed code? I haven't find any. Thanks a lot. Iva

Re:Invalid Characters April 25, 2012 by Christoff Truter

Hi there I actually fixed this exact same issue for someone a while ago, but didnt update the source code on the site yet, I will have a look at it tonight sometime and update the source code for you.

Problem with some characters at ListPicker April 25, 2012 by Iva

dear Christoff, thanks a lot for your code. It's very useful for me. So I found the problem when I use for example Czech characters (á,,&#269; and every others) - when page is loaded (ASP.Net VB), everything it's OK, when I move some items between source and destinations listboxes in listpicker and click to proceed button, this source and destination listboxes include bad characters - I can send screenshot if you would like. The rest lispickers, where I haven't moved any item, are OK. Can you help me? I use encoding utf-8 at ASPX pages and MS SQL database too. Thank you.


Latest Posts

Enhance Customer Registration Process with Cutting-Edge Solutions from Card Scanning Solutions Inc.

November 4, 2013

JavaScript Threading - Part 2 (Worker)

December 18, 2012

JavaScript Threading - Part 1 (Timers)

December 18, 2012

MS SQL: Parameter Sniffing

May 21, 2012

Solving Cross Browser Issues - Part 3 (Mootools and HTML5)

February 23, 2012

Solving Cross Browser Issues - Part 2 (GWT and Dart)

February 7, 2012

Solving Cross Browser Issues - Part 1 (JQuery and GWT)

January 9, 2012

Be the best stalker you can be

December 13, 2011

AjaxControlToolkit (ASP.NET/C#) : CascadingDropDown Extender - Part 2

November 3, 2011

AjaxControlToolkit (ASP.NET/C#) : CascadingDropDown Extender - Part 1

October 7, 2011


Most Commented on Posts

Moving items between listboxes in ASP.net/PHP example

Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
June 12, 2008

Simple WYSIWYG Editor

Creating a WYSIWYG textbox for your website is actually quite simple.
February 1, 2007

C# YouTube : Google API

Post on how to integrate with YouTube using the Google Data API
March 12, 2011

Populate a TreeView Control C#

Populate a TreeView control in a windows application.
August 27, 2009

Cross Browser Issues: Firefox Word Wrapping

Firefox word wrapping issues
June 9, 2008


ASP.NET   C#   C++   Comedy   Cross Browser   Design Patterns   IIS   Integration   JavaScript   Microsoft Office   Personal   PHP   SQL   Threading   Visual Basic   XML