CustomWebControl with client script

L

Lance

Hello All.

I have created my first custom web control to use client
side script to move items from one list box to another
(thanks Andy Smith for the inspiration even though I
couldnt understand the C# code).

The only way I could get the items in the boxes to persist
accross postbacks was to concat the lists in to a string
and write the string , via a hidden field, to the
viewstate.
Then on re-rendering I have to un-concat the string back
into its elements.

I would be happier if I could write a more complex object
like a ListBox object to the viewstate.
Is this possible?

Ideas and comments gratefull accepted.

Lance

Code so far .....
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.ComponentModel
Imports System.Collections.Specialized

<DefaultProperty("Text"), ToolboxData("<{0}:LancesListBox
runat=server></{0}:LancesListBox>")> _
Public Class LancesListBox
Inherits WebControl
Implements INamingContainer
Implements IPostBackDataHandler

Dim vDropListItems As New ListItemCollection()
Dim vListItems As New ListItemCollection()

Public Property DropListItems() As ListItemCollection
Get
vDropListItems.Clear()
Dim StoredValues As String = CType(ViewState
(UniqueID & "_DropList_Storage"), String)
If Not StoredValues = "" Then
Dim aryItems() As String
Dim i As Int16
aryItems = Split(StoredValues, "@@")
For i = 1 To aryItems.Length - 1
Dim aryValues() As String
aryValues = Split(aryItems(i), "//", 2)
Dim li As New ListItem(aryValues(0),
aryValues(1))
vDropListItems.Add(li)
Next
End If
Return vDropListItems
End Get
Set(ByVal Value As ListItemCollection)
Dim strStorage As String
Dim li As New ListItem()
For Each li In Value
strStorage = strStorage & "@@" & li.Text
& "//" & li.Value
Next
ViewState(UniqueID & "_DropList_Storage") =
strStorage
End Set
End Property

Public Property ListItems() As ListItemCollection
Get
vListItems.Clear()
Dim StoredValues As String = CType(ViewState
(UniqueID & "_List_Storage"), String)
If Not StoredValues = "" Then
Dim aryItems() As String
Dim i As Int16
aryItems = Split(StoredValues, "@@")
For i = 1 To aryItems.Length - 1
Dim aryValues() As String
aryValues = Split(aryItems(i), "//", 2)
Dim li As New ListItem(aryValues(0),
aryValues(1))
vListItems.Add(li)
Next
End If
Return vListItems
End Get
Set(ByVal Value As ListItemCollection)
Dim strStorage As String
Dim li As New ListItem()
For Each li In Value
strStorage = strStorage & "@@" & li.Text
& "//" & li.Value
Next
ViewState(UniqueID & "_List_Storage") =
strStorage
End Set
End Property

Protected Overrides Sub OnPreRender(ByVal e As
System.EventArgs)
Page.RegisterRequiresPostBack(Me)
'Send the Java script to the client
Dim strScript As String = GetJavaScripts()

'check to see if a copy has already been sent
'if there is more than one instance of the control
on the page
If (Not Page.IsClientScriptBlockRegistered
("LancesListBoxScript")) Then
Page.RegisterClientScriptBlock
("LancesListBoxScript", strScript)
End If
End Sub

Protected Overrides Sub Render(ByVal output As
System.Web.UI.HtmlTextWriter)
'The table to hold the controls
output.RenderBeginTag("table")
output.RenderBeginTag("tr")
output.RenderBeginTag("td")

'the drop down list
output.AddAttribute("name", Me.UniqueID
& "_DropList")
output.AddAttribute("style", "width:120")
output.RenderBeginTag("select")

'add items to the DropDownList
'This also repopulates the list
'from info in the ViewState during postbacks
Dim li As New ListItem()
For Each li In DropListItems
output.AddAttribute("value", li.Value)
output.RenderBeginTag("option")
output.Write(li.Text)
output.RenderEndTag() '</option>
Next

output.RenderEndTag() '</select>

'the dropdown storage
'this is a hidden field to persist dropdownList
info
'During postback it reloads itself from the
viewstate
output.AddAttribute("name", Me.UniqueID
& "_DropList_Storage")
output.AddAttribute("type", "hidden")
output.AddAttribute("value", CType(ViewState
(UniqueID & "_DropList_Storage"), String))
output.RenderBeginTag("input")
output.RenderEndTag()

'The add button
output.AddAttribute("name", Me.UniqueID & "_Add")
output.AddAttribute("type", "button")
output.AddAttribute("style", "width:22;Height:22")
output.AddAttribute("onclick", "moveDualList( " &
UniqueID & "_DropList, " & UniqueID & "_List, " & UniqueID
& "_DropList_Storage, " & UniqueID & "_List_Storage, " &
UniqueID & "_DropList, " & UniqueID & "_List )")
output.AddAttribute("value", "+")
output.RenderBeginTag("input")
output.RenderEndTag() '</input>

output.RenderEndTag() '</td>
output.RenderEndTag() '</tr>
output.RenderBeginTag("tr")
output.RenderBeginTag("td")

'the list
output.AddAttribute("name", Me.UniqueID & "_List")
output.AddAttribute("style", "width:120")
output.AddAttribute("size", "4")
output.RenderBeginTag("select")

'add items to the ListBox
'This also repopulates the list
'from info in the ViewState during postbacks
For Each li In ListItems
output.AddAttribute("value", li.Value)
output.RenderBeginTag("option")
output.Write(li.Text)
output.RenderEndTag() '</option>
Next
output.RenderEndTag() '</select>

'the list storage
'this is a hidden field to persist List info
'During postback it reloads itself from the
viewstate
output.AddAttribute("name", Me.UniqueID
& "_List_Storage")
output.AddAttribute("type", "hidden")
output.AddAttribute("value", CType(ViewState
(UniqueID & "_List_Storage"), String))
output.RenderBeginTag("input")
output.RenderEndTag()

'The remove button
output.AddAttribute("name", Me.UniqueID
& "_Remove")
output.AddAttribute("type", "button")
output.AddAttribute("style", "width:22;Height:22")
'THe onclick event fires the JavaScript to do the
work
output.AddAttribute("onclick", "moveDualList( " &
UniqueID & "_List, " & UniqueID & "_DropList, " & UniqueID
& "_DropList_Storage, " & UniqueID & "_List_Storage, " &
UniqueID & "_DropList, " & UniqueID & "_List )")
output.AddAttribute("value", "-")
output.RenderBeginTag("input")
output.RenderEndTag()

output.RenderEndTag() '</td>
output.RenderEndTag() '</tr>
output.RenderEndTag() '</table>
End Sub

'Writes the page values to the ViewState so they
persist after postback
Public Overridable Function LoadPostData(ByVal
postDataKey As String, ByVal values As
NameValueCollection) As Boolean Implements
IPostBackDataHandler.LoadPostData
ViewState(UniqueID & "_List_Storage") = values
(postDataKey & "_List_Storage")
ViewState(UniqueID & "_DropList_Storage") = values
(postDataKey & "_DropList_Storage")
Return True
End Function

'This is required
Public Overridable Sub RaisePostDataChangedEvent()
Implements IPostBackDataHandler.RaisePostDataChangedEvent
' Dont know why
End Sub

'Put togeather the Javascript to output
Private Function GetJavaScripts() As String
Dim sbScript As New System.Text.StringBuilder
("<script language=""JavaScript"">")
sbScript.Append(ControlChars.CrLf)
sbScript.Append("<!-- Begin")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(ControlChars.CrLf)
'// Sort the items in a Listbox
sbScript.Append("function Sort_ListBox(box) {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" var tmp = new Array();")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" var len = box.options.length;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" for (i = 0; i < len; i++) {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" tmp = new Array(box.options
.text.toLowerCase(), new Object(box.options));")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" tmp.sort();")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" box.options.length = 0;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" for (i = 0; i < len; i++)
box.options.add(tmp[1]);")
sbScript.Append(ControlChars.CrLf)
sbScript.Append("}")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(ControlChars.CrLf)
'// Dual list move function
sbScript.Append("function moveDualList( srcList,
destList, dropStorage, listStorage, dropList, list ) {")
sbScript.Append(ControlChars.CrLf)
'// Do nothing if nothing is selected
sbScript.Append(" if ( srcList.selectedIndex == -
1 )")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" { return; }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" var len = (
destList.options.length );")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" var sel =
(srcList.selectedIndex);")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" var exists = false;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(ControlChars.CrLf)

'//See if the item already exists in the
destination list
sbScript.Append(" for( i = 0; i <
destList.options.length; i++ ) ")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" if ( destList.options[
i ].text == srcList.options[ sel ].text )")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" exists = true;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" if (exists == false)")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
'//Add item to destinationlist
sbScript.Append(" destList[ len ] = new Option(
srcList.options[ sel ].text, srcList.options[ sel ].value,
srcList.options[ sel ].defaultSelected, srcList.options[
sel ].selected );")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
'//Delete item from source list
sbScript.Append(" srcList.options[sel] = null;")
sbScript.Append(ControlChars.CrLf)
'//Sort the destination List
sbScript.Append(" Sort_ListBox(destList)")
sbScript.Append(ControlChars.CrLf)
'//Read The Listbox Items and Write them as a
String for storage
sbScript.Append(" var listString = """";")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" for( k = 0; k <
list.options.length; k++ ) ")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" if ( list.options[ k ] !=
null )")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" listString = listString
+ ""@@"" + list.options[ k ].text + ""//"" + list.options[
k ].value;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" listStorage.value = listString")
sbScript.Append(ControlChars.CrLf)
'//Read the DropList items and store them as a
string
sbScript.Append(" var dropString = """";")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" for( var m = 0; m <
dropList.options.length; m++ ) ")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" if ( dropList.options[ m ] !=
null )")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" dropString = dropString
+ ""@@"" + dropList.options[ m ].text + ""//"" +
dropList.options[ m ].value;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" dropStorage.value = dropString")
sbScript.Append(ControlChars.CrLf)

'//Select the next item on the sourcelist
sbScript.Append(" if ( srcList.options.length >
sel )")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" srcList.options[sel].selected
= true;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" else")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" if ( sel != 0 )")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" {")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" srcList.options[sel -
1].selected = true;")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append(" }")
sbScript.Append(ControlChars.CrLf)
sbScript.Append("} // End of moveDualList()")
sbScript.Append(ControlChars.CrLf)
sbScript.Append("// End -->")
sbScript.Append(ControlChars.CrLf)
sbScript.Append("</script>")
sbScript.Append(ControlChars.CrLf)
Return sbScript.ToString
End Function

End Class
 
J

John Saunders

Lance said:
Hello All.

I have created my first custom web control to use client
side script to move items from one list box to another
(thanks Andy Smith for the inspiration even though I
couldnt understand the C# code).

The only way I could get the items in the boxes to persist
accross postbacks was to concat the lists in to a string
and write the string , via a hidden field, to the
viewstate.
Then on re-rendering I have to un-concat the string back
into its elements.

I would be happier if I could write a more complex object
like a ListBox object to the viewstate.
Is this possible?

ViewState is optimized to hold a certain restricted set of object types.
See:

Maintaining State in a Control
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/ht
ml/cpconmantainingstateincontrol.asp)



From that document:

Types That Can Be Persisted in ViewState

A type that either is serializable or has a TypeConverter defined for it can
be persisted in ViewState. However, types that are only serializable are
slower and generate a much larger ViewState than those that have a
TypeConverter. ViewState is serialized using a limited object serialization
format that is optimized for primitive types, and for String, ArrayList, and
HashTable types.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top