增强DropDownList和ListBox控件:保持客户端脚本添加的options

 

        DropDownList、ListBox由于Items是保存在ViewState中,回传后服务端会从ViewState恢复所有Items,所以,客户端对options的设置在回传后无法获取、保持。
        一个解决思路是通过在页面Submit的时候,在客户端解码viewstate,找出相应items集合,根据客户端对该集合的处理,进行重新设置,然后再把更改过的viewstate重新编码提交。由于一个页面的viewstate可以是非常之大,所以这个操作在客户端的压力可能会较大。
        另一个思路是将客户端对options的变更保存到隐藏域中提交,然后服务端根据该隐藏域的信息重建ListControl的items。相对而言,该实现效率更高。这个解决方案就是基于该思路来做的。我继承DropDownList、ListBox,让每个控件实例与一个隐藏域一起输出到客户端,在客户端Form.onsubmit事件时,通过脚本把客户对该Select控件所包含options的变更,以xml保存到隐藏域。然后在控件的处理CreateChildControls事件时,分析该隐藏域的内容,解析并创建出各ListItem。
        以下是解决方案结构图:
增强DropDownList和ListBox控件:保持客户端脚本添加的options
在ClientOptionsHolder项目里,ClientOptionsHolder.js包含把options存入隐藏域的客户端脚本。代码如下:

增强DropDownList和ListBox控件:保持客户端脚本添加的options function  GetAttributes_BB49C217_C465_4163_97D6_69568B71A502(oElem)
增强DropDownList和ListBox控件:保持客户端脚本添加的options
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
var oAttribs = oElem.attributes;
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
var s = "";
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
for (var i = 0; i < oAttribs.length; i++)
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
var oAttrib = oAttribs[i];
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
if(oAttrib.specified && oAttrib.nodeName!='selected')
增强DropDownList和ListBox控件:保持客户端脚本添加的options            s 
+= ' ' + oAttrib.nodeName + '="' + oAttrib.nodeValue + '"';
增强DropDownList和ListBox控件:保持客户端脚本添加的options    }

增强DropDownList和ListBox控件:保持客户端脚本添加的options    
if(oAttribs.getNamedItem("selected").value == 'true')
增强DropDownList和ListBox控件:保持客户端脚本添加的options        s 
+= ' selected="true"'; 
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
return s;
增强DropDownList和ListBox控件:保持客户端脚本添加的options}

增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的options
function  StoreClientOptions_BB49C217_C465_4163_97D6_69568B71A502(oSelect,oHidden)
增强DropDownList和ListBox控件:保持客户端脚本添加的options
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options        oHidden.value 
= ""
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
for(i=0;i<oSelect.options.length;i++)
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options            oOption 
= oSelect.options[i];
增强DropDownList和ListBox控件:保持客户端脚本添加的options            attrs 
= GetAttributes_BB49C217_C465_4163_97D6_69568B71A502(oOption);
增强DropDownList和ListBox控件:保持客户端脚本添加的options            oHidden.value 
+='<item text="'+oOption.text+'"+ attrs +'/>"';
增强DropDownList和ListBox控件:保持客户端脚本添加的options        }
增强DropDownList和ListBox控件:保持客户端脚本添加的options        oHidden.value += 
"items>"
增强DropDownList和ListBox控件:保持客户端脚本添加的options        oHidden.value=escape(oHidden.value);
增强DropDownList和ListBox控件:保持客户端脚本添加的options}
       第一个函数是用来获取各个option的属性集合。只有明确设定了的属性(通过Attribute.specified判断)以及opton的select属性是true时,才添加到集合中。
      第二个函数的作用是把指定Select的options以被escape编码的xml的格式放入对应隐藏域。

        继承的DropDownList代码如下,非常简单:
增强DropDownList和ListBox控件:保持客户端脚本添加的options using System;
增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Collections.Generic;
增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Text;
增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Web.UI.WebControls;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的optionsnamespace ZiffWong.Exercise.ControlLibrary
增强DropDownList和ListBox控件:保持客户端脚本添加的options
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options    public class DropDownList : System.Web.UI.WebControls.DropDownList
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options        ClientOptionsHolder _StateHolder;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的options        public DropDownList()
增强DropDownList和ListBox控件:保持客户端脚本添加的options            : base()
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options            _StateHolder 
= new ClientOptionsHolder(this);
增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的options        protected override 
void CreateChildControls()
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options            
if (!Page.IsPostBack || !this.EnableViewState)
增强DropDownList和ListBox控件:保持客户端脚本添加的options                base.CreateChildControls();
增强DropDownList和ListBox控件:保持客户端脚本添加的options            
else
增强DropDownList和ListBox控件:保持客户端脚本添加的options                _StateHolder.SetItemsForPostBack();
增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

增强DropDownList和ListBox控件:保持客户端脚本添加的options    }

增强DropDownList和ListBox控件:保持客户端脚本添加的options}

增强DropDownList和ListBox控件:保持客户端脚本添加的options
        它在初始化的时候指定了一个ClientOptionsHolder,将自身作为参数传递给它;然后在CreateChildControls时,判断到当前页面状态如果是从客户端回传时,则让ClientOptionsHolder的SetItemsForPostBack()来处理Items的生成。可见,控件能够保存客户端设置的细节,是由ClientOptionsHolder来实现的。下面来看这个ClientOptionsHolder的具体实现:
增强DropDownList和ListBox控件:保持客户端脚本添加的options ClientOptionsHolder.cs
 1增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System;
 2增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Collections.Generic;
 3增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Text;
 4增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Web.UI.WebControls;
 5增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Web;
 6增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Web.UI;
 7增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System.Xml;
 8增强DropDownList和ListBox控件:保持客户端脚本添加的options
 9增强DropDownList和ListBox控件:保持客户端脚本添加的optionsnamespace ZiffWong.Exercise.ControlLibrary
10增强DropDownList和ListBox控件:保持客户端脚本添加的options{
11增强DropDownList和ListBox控件:保持客户端脚本添加的options    /// 
12增强DropDownList和ListBox控件:保持客户端脚本添加的options    /// Hodes options from client.
13增强DropDownList和ListBox控件:保持客户端脚本添加的options    /// 

14增强DropDownList和ListBox控件:保持客户端脚本添加的options    public class ClientOptionsHolder
15增强DropDownList和ListBox控件:保持客户端脚本添加的options    {
16增强DropDownList和ListBox控件:保持客户端脚本添加的options        const string GUID = "BB49C217_C465_4163_97D6_69568B71A502";
17增强DropDownList和ListBox控件:保持客户端脚本添加的options        string SETHIDDENFILED_FUNCTONNAME = "StoreClientOptions_" + GUID;
18增强DropDownList和ListBox控件:保持客户端脚本添加的options        Type myType = typeof(ClientOptionsHolder);
19增强DropDownList和ListBox控件:保持客户端脚本添加的options        ListControl controlToHold;
20增强DropDownList和ListBox控件:保持客户端脚本添加的options
21增强DropDownList和ListBox控件:保持客户端脚本添加的options        string HIDDEN_FIELD_KEY
22增强DropDownList和ListBox控件:保持客户端脚本添加的options        {
23增强DropDownList和ListBox控件:保持客户端脚本添加的options            get
24增强DropDownList和ListBox控件:保持客户端脚本添加的options            {
25增强DropDownList和ListBox控件:保持客户端脚本添加的options                return controlToHold.ClientID + "_MemField";
26增强DropDownList和ListBox控件:保持客户端脚本添加的options            }

27增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

28增强DropDownList和ListBox控件:保持客户端脚本添加的options
29增强DropDownList和ListBox控件:保持客户端脚本添加的options        public ClientOptionsHolder(ListControl control)
30增强DropDownList和ListBox控件:保持客户端脚本添加的options        {
31增强DropDownList和ListBox控件:保持客户端脚本添加的options            this.controlToHold = control;
32增强DropDownList和ListBox控件:保持客户端脚本添加的options            controlToHold.PreRender += new EventHandler(control_PreRender);
33增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

34增强DropDownList和ListBox控件:保持客户端脚本添加的options
35增强DropDownList和ListBox控件:保持客户端脚本添加的options        public void SetItemsForPostBack()
36增强DropDownList和ListBox控件:保持客户端脚本添加的options        {
37增强DropDownList和ListBox控件:保持客户端脚本添加的options            if (!controlToHold.Page.IsPostBack)
38增强DropDownList和ListBox控件:保持客户端脚本添加的options                return;
39增强DropDownList和ListBox控件:保持客户端脚本添加的options
40增强DropDownList和ListBox控件:保持客户端脚本添加的options            XmlDocument doc = new XmlDocument();
41增强DropDownList和ListBox控件:保持客户端脚本添加的options            doc.LoadXml(HttpContext.Current.Server.UrlDecode(HttpContext.Current.Request.Form[HIDDEN_FIELD_KEY]));
42增强DropDownList和ListBox控件:保持客户端脚本添加的options            XmlNodeList nodes = doc.SelectNodes("/items/item");
43增强DropDownList和ListBox控件:保持客户端脚本添加的options
44增强DropDownList和ListBox控件:保持客户端脚本添加的options            controlToHold.Items.Clear();
45增强DropDownList和ListBox控件:保持客户端脚本添加的options            foreach (XmlNode node in nodes)
46增强DropDownList和ListBox控件:保持客户端脚本添加的options            {
47增强DropDownList和ListBox控件:保持客户端脚本添加的options                // Set text and value.
48增强DropDownList和ListBox控件:保持客户端脚本添加的options                string itemValue;
49增强DropDownList和ListBox控件:保持客户端脚本添加的options                string itemText;
50增强DropDownList和ListBox控件:保持客户端脚本添加的options                itemText = node.Attributes["text"== null ? null : node.Attributes["text"].InnerText;
51增强DropDownList和ListBox控件:保持客户端脚本添加的options                itemValue = node.Attributes["value"== null ? null : node.Attributes["value"].InnerText;
52增强DropDownList和ListBox控件:保持客户端脚本添加的options                ListItem li = new ListItem(itemText, itemValue);
53增强DropDownList和ListBox控件:保持客户端脚本添加的options
54增强DropDownList和ListBox控件:保持客户端脚本添加的options                //Set selected.
55增强DropDownList和ListBox控件:保持客户端脚本添加的options                if (node.Attributes["selected"!= null && node.Attributes["selected"].Value == "true")
56增强DropDownList和ListBox控件:保持客户端脚本添加的options                    li.Selected = true;
57增强DropDownList和ListBox控件:保持客户端脚本添加的options
58增强DropDownList和ListBox控件:保持客户端脚本添加的options                ////Those ListItems with "Enabled"==false will not be added to items collection because they will not render any outputs.
59增强DropDownList和ListBox控件:保持客户端脚本添加的options                //if (node.Attributes["disabled"] != null)
60增强DropDownList和ListBox控件:保持客户端脚本添加的options                //li.Enabled = false;
61增强DropDownList和ListBox控件:保持客户端脚本添加的options
62增强DropDownList和ListBox控件:保持客户端脚本添加的options                //Apply other attributes such as "label","isMultiLine" etc.
63增强DropDownList和ListBox控件:保持客户端脚本添加的options                foreach (XmlAttribute attr in node.Attributes)
64增强DropDownList和ListBox控件:保持客户端脚本添加的options                {
65增强DropDownList和ListBox控件:保持客户端脚本添加的options                    string attrName = attr.Name;
66增强DropDownList和ListBox控件:保持客户端脚本添加的options                    if (attrName != "text" && attrName != "value" && attrName != "selected")
67增强DropDownList和ListBox控件:保持客户端脚本添加的options                    {
68增强DropDownList和ListBox控件:保持客户端脚本添加的options                        li.Attributes.Add(attrName, attr.Value);
69增强DropDownList和ListBox控件:保持客户端脚本添加的options                    }

70增强DropDownList和ListBox控件:保持客户端脚本添加的options                }

71增强DropDownList和ListBox控件:保持客户端脚本添加的options
72增强DropDownList和ListBox控件:保持客户端脚本添加的options                controlToHold.Items.Add(li);
73增强DropDownList和ListBox控件:保持客户端脚本添加的options            }

74增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

75增强DropDownList和ListBox控件:保持客户端脚本添加的options
76增强DropDownList和ListBox控件:保持客户端脚本添加的options        void control_PreRender(object sender, EventArgs e)
77增强DropDownList和ListBox控件:保持客户端脚本添加的options        {
78增强DropDownList和ListBox控件:保持客户端脚本添加的options            string senderClientID = ((ListControl)sender).ClientID;
79增强DropDownList和ListBox控件:保持客户端脚本添加的options            Control control = (Control)sender;
80增强DropDownList和ListBox控件:保持客户端脚本添加的options            string onSubmitScriptKey = string.Format("SetHiddenField_{0}", senderClientID);
81增强DropDownList和ListBox控件:保持客户端脚本添加的options            if (!control.Page.ClientScript.IsOnSubmitStatementRegistered(myType, onSubmitScriptKey))
82增强DropDownList和ListBox控件:保持客户端脚本添加的options            {
83增强DropDownList和ListBox控件:保持客户端脚本添加的options                control.Page.ClientScript.RegisterClientScriptResource(myType, "ZiffWong.Exercise.ControlLibrary.ClientOptionsHolders.js");
84增强DropDownList和ListBox控件:保持客户端脚本添加的options
85增强DropDownList和ListBox控件:保持客户端脚本添加的options                string scriptBody = SETHIDDENFILED_FUNCTONNAME + string.Format("(document.all.{0},document.all.{1});", senderClientID, HIDDEN_FIELD_KEY);
86增强DropDownList和ListBox控件:保持客户端脚本添加的options                control.Page.ClientScript.RegisterOnSubmitStatement(myType, onSubmitScriptKey, scriptBody);
87增强DropDownList和ListBox控件:保持客户端脚本添加的options                control.Page.ClientScript.RegisterClientScriptBlock(myType, HIDDEN_FIELD_KEY, string.Format(""hidden\" id=\"{0}\" name=\"{0}\"/>", HIDDEN_FIELD_KEY));
88增强DropDownList和ListBox控件:保持客户端脚本添加的options
89增强DropDownList和ListBox控件:保持客户端脚本添加的options            }

90增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

91增强DropDownList和ListBox控件:保持客户端脚本添加的options    }

92增强DropDownList和ListBox控件:保持客户端脚本添加的options}

93增强DropDownList和ListBox控件:保持客户端脚本添加的options

        它的初始化函数中把传入的ListControl的PreRender事件挂接control_PreRender  函数,该函数首先把上面的Javascript资源链接注册到页面,然后在客户端的OnSubmit中添加对保存options到隐藏域的JS函数的调用。最后,把隐藏域输出到客户端。
        SetItemsForPostBack()由挂接该ClientOptionsHolder的ListControl在CreateChildControls时调用。它解析客户端隐藏域里面的xml,据此生成所有Items集合。
        为了能够使用dll内嵌的资源文件,需要在AssemblyInfo.cs中做如下设置:
[assembly: System.Web.UI.TagPrefix( " ZiffWong.Exercise.ControlLibrary " " mstc " )]
[assembly: System.Web.UI.WebResource(
" ZiffWong.Exercise.ControlLibrary.ClientOptionsHolders.js " " application/x-javascript " )]


        注意在资源文件ClientOptionsHolders.js前需要加上该控件所在程序集的默认命名空间。程序中对该资源的引用也需要如此处理。

对ListBox的处理和DropDownList一样:

增强DropDownList和ListBox控件:保持客户端脚本添加的options

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing System;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
using System.Collections.Generic;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
using System.Text;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
using System.Web.UI.WebControls;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的options
namespace ZiffWong.Exercise.ControlLibrary
增强DropDownList和ListBox控件:保持客户端脚本添加的options
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
public class ListBox : System.Web.UI.WebControls.ListBox
增强DropDownList和ListBox控件:保持客户端脚本添加的options    
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options        ClientOptionsHolder _StateHolder;
增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
public ListBox()
增强DropDownList和ListBox控件:保持客户端脚本添加的options            : 
base()
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options            _StateHolder 
= new ClientOptionsHolder(this);
增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

增强DropDownList和ListBox控件:保持客户端脚本添加的options
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
protected override void CreateChildControls()
增强DropDownList和ListBox控件:保持客户端脚本添加的options        
{
增强DropDownList和ListBox控件:保持客户端脚本添加的options            
if (!Page.IsPostBack || !this.EnableViewState)
增强DropDownList和ListBox控件:保持客户端脚本添加的options                
base.CreateChildControls();
增强DropDownList和ListBox控件:保持客户端脚本添加的options            
else
增强DropDownList和ListBox控件:保持客户端脚本添加的options                _StateHolder.SetItemsForPostBack();
增强DropDownList和ListBox控件:保持客户端脚本添加的options        }

增强DropDownList和ListBox控件:保持客户端脚本添加的options    }

增强DropDownList和ListBox控件:保持客户端脚本添加的options}

你可能感兴趣的:(listbox)