增强DropDownList和ListBox控件:保持客户端脚本添加的options
生活随笔
收集整理的這篇文章主要介紹了
增强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。
??????? 以下是解決方案結構圖:
在ClientOptionsHolder項目里,ClientOptionsHolder.js包含把options存入隱藏域的客戶端腳本。代碼如下:
function?GetAttributes_BB49C217_C465_4163_97D6_69568B71A502(oElem)
{
????var?oAttribs?=?oElem.attributes;
????var?s?=?"";
????for?(var?i?=?0;?i?<?oAttribs.length;?i++)
????{
????????var?oAttrib?=?oAttribs[i];
????????if(oAttrib.specified?&&?oAttrib.nodeName!='selected')
????????????s?+=?'?'?+?oAttrib.nodeName?+?'="'?+?oAttrib.nodeValue?+?'"';
????}
????if(oAttribs.getNamedItem("selected").value?==?'true')
????????s?+=?'?selected="true"';?
????return?s;
}
function?StoreClientOptions_BB49C217_C465_4163_97D6_69568B71A502(oSelect,oHidden)
{
????????oHidden.value?=?"";?
????????for(i=0;i<oSelect.options.length;i++)
????????{
????????????oOption?=?oSelect.options[i];
????????????attrs?=?GetAttributes_BB49C217_C465_4163_97D6_69568B71A502(oOption);
????????????oHidden.value?+='<item?text="'+oOption.text+'"'?+?attrs?+'/>"';
????????}
????????oHidden.value?+=?"items>";?
????????oHidden.value=escape(oHidden.value);
} ?????? 第一個函數是用來獲取各個option的屬性集合。只有明確設定了的屬性(通過Attribute.specified判斷)以及opton的select屬性是true時,才添加到集合中。
????? 第二個函數的作用是把指定Select的options以被escape編碼的xml的格式放入對應隱藏域。
??????? 繼承的DropDownList代碼如下,非常簡單:
using?System;
using?System.Collections.Generic;
using?System.Text;
using?System.Web.UI.WebControls;
namespace?ZiffWong.Exercise.ControlLibrary
{
????public?class?DropDownList?:?System.Web.UI.WebControls.DropDownList
????{
????????ClientOptionsHolder?_StateHolder;
????????public?DropDownList()
????????????:?base()
????????{
????????????_StateHolder?=?new?ClientOptionsHolder(this);
????????}
????????protected?override?void?CreateChildControls()
????????{
????????????if?(!Page.IsPostBack?||?!this.EnableViewState)
????????????????base.CreateChildControls();
????????????else
????????????????_StateHolder.SetItemsForPostBack();
????????}
????}
}
??????? 它在初始化的時候指定了一個ClientOptionsHolder,將自身作為參數傳遞給它;然后在CreateChildControls時,判斷到當前頁面狀態如果是從客戶端回傳時,則讓ClientOptionsHolder的SetItemsForPostBack()來處理Items的生成。可見,控件能夠保存客戶端設置的細節,是由ClientOptionsHolder來實現的。下面來看這個ClientOptionsHolder的具體實現:
ClientOptionsHolder.cs
?1using?System;
?2using?System.Collections.Generic;
?3using?System.Text;
?4using?System.Web.UI.WebControls;
?5using?System.Web;
?6using?System.Web.UI;
?7using?System.Xml;
?8
?9namespace?ZiffWong.Exercise.ControlLibrary
10{
11????/**////?
12????///?Hodes?options?from?client.
13????///?
14????public?class?ClientOptionsHolder
15????{
16????????const?string?GUID?=?"BB49C217_C465_4163_97D6_69568B71A502";
17????????string?SETHIDDENFILED_FUNCTONNAME?=?"StoreClientOptions_"?+?GUID;
18????????Type?myType?=?typeof(ClientOptionsHolder);
19????????ListControl?controlToHold;
20
21????????string?HIDDEN_FIELD_KEY
22????????{
23????????????get
24????????????{
25????????????????return?controlToHold.ClientID?+?"_MemField";
26????????????}
27????????}
28
29????????public?ClientOptionsHolder(ListControl?control)
30????????{
31????????????this.controlToHold?=?control;
32????????????controlToHold.PreRender?+=?new?EventHandler(control_PreRender);
33????????}
34
35????????public?void?SetItemsForPostBack()
36????????{
37????????????if?(!controlToHold.Page.IsPostBack)
38????????????????return;
39
40????????????XmlDocument?doc?=?new?XmlDocument();
41????????????doc.LoadXml(HttpContext.Current.Server.UrlDecode(HttpContext.Current.Request.Form[HIDDEN_FIELD_KEY]));
42????????????XmlNodeList?nodes?=?doc.SelectNodes("/items/item");
43
44????????????controlToHold.Items.Clear();
45????????????foreach?(XmlNode?node?in?nodes)
46????????????{
47????????????????//?Set?text?and?value.
48????????????????string?itemValue;
49????????????????string?itemText;
50????????????????itemText?=?node.Attributes["text"]?==?null???null?:?node.Attributes["text"].InnerText;
51????????????????itemValue?=?node.Attributes["value"]?==?null???null?:?node.Attributes["value"].InnerText;
52????????????????ListItem?li?=?new?ListItem(itemText,?itemValue);
53
54????????????????//Set?selected.
55????????????????if?(node.Attributes["selected"]?!=?null?&&?node.Attributes["selected"].Value?==?"true")
56????????????????????li.Selected?=?true;
57
58????????????????/**/////Those?ListItems?with?"Enabled"==false?will?not?be?added?to?items?collection?because?they?will?not?render?any?outputs.
59????????????????//if?(node.Attributes["disabled"]?!=?null)
60????????????????//li.Enabled?=?false;
61
62????????????????//Apply?other?attributes?such?as?"label","isMultiLine"?etc.
63????????????????foreach?(XmlAttribute?attr?in?node.Attributes)
64????????????????{
65????????????????????string?attrName?=?attr.Name;
66????????????????????if?(attrName?!=?"text"?&&?attrName?!=?"value"?&&?attrName?!=?"selected")
67????????????????????{
68????????????????????????li.Attributes.Add(attrName,?attr.Value);
69????????????????????}
70????????????????}
71
72????????????????controlToHold.Items.Add(li);
73????????????}
74????????}
75
76????????void?control_PreRender(object?sender,?EventArgs?e)
77????????{
78????????????string?senderClientID?=?((ListControl)sender).ClientID;
79????????????Control?control?=?(Control)sender;
80????????????string?onSubmitScriptKey?=?string.Format("SetHiddenField_{0}",?senderClientID);
81????????????if?(!control.Page.ClientScript.IsOnSubmitStatementRegistered(myType,?onSubmitScriptKey))
82????????????{
83????????????????control.Page.ClientScript.RegisterClientScriptResource(myType,?"ZiffWong.Exercise.ControlLibrary.ClientOptionsHolders.js");
84
85????????????????string?scriptBody?=?SETHIDDENFILED_FUNCTONNAME?+?string.Format("(document.all.{0},document.all.{1});",?senderClientID,?HIDDEN_FIELD_KEY);
86????????????????control.Page.ClientScript.RegisterOnSubmitStatement(myType,?onSubmitScriptKey,?scriptBody);
87????????????????control.Page.ClientScript.RegisterClientScriptBlock(myType,?HIDDEN_FIELD_KEY,?string.Format(""hidden\"?id=\"{0}\"?name=\"{0}\"/>",?HIDDEN_FIELD_KEY));
88
89????????????}
90????????}
91????}
92}
93
??????? 它的初始化函數中把傳入的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一樣:
ListBox.csCode highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->using?System;
using?System.Collections.Generic;
using?System.Text;
using?System.Web.UI.WebControls;
namespace?ZiffWong.Exercise.ControlLibrary
{
????public?class?ListBox?:?System.Web.UI.WebControls.ListBox
????{
????????ClientOptionsHolder?_StateHolder;
????????public?ListBox()
????????????:?base()
????????{
????????????_StateHolder?=?new?ClientOptionsHolder(this);
????????}
????????protected?override?void?CreateChildControls()
????????{
????????????if?(!Page.IsPostBack?||?!this.EnableViewState)
????????????????base.CreateChildControls();
????????????else
????????????????_StateHolder.SetItemsForPostBack();
????????}
????}
}
總結
以上是生活随笔為你收集整理的增强DropDownList和ListBox控件:保持客户端脚本添加的options的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: J2EE从头开始__EJB3
- 下一篇: CCNA沈阳考点