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控件:保持客户端脚本添加的optionsfunction GetAttributes_BB49C217_C465_4163_97D6_69568B71A502(oElem)
}
       第一个函数是用来获取各个option的属性集合。只有明确设定了的属性(通过Attribute.specified判断)以及opton的select属性是true时,才添加到集合中。
      第二个函数的作用是把指定Select的options以被escape编码的xml的格式放入对应隐藏域。

        继承的DropDownList代码如下,非常简单:
增强DropDownList和ListBox控件:保持客户端脚本添加的optionsusing 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
        它在初始化的时候指定了一个ClientOptionsHolder,将自身作为参数传递给它;然后在CreateChildControls时,判断到当前页面状态如果是从客户端回传时,则让ClientOptionsHolder的SetItemsForPostBack()来处理Items的生成。可见,控件能够保存客户端设置的细节,是由ClientOptionsHolder来实现的。下面来看这个ClientOptionsHolder的具体实现:

        它的初始化函数中把传入的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一样:

}

相关文章: