zoukankan      html  css  js  c++  java
  • 增强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一样:



    Code 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();
            }

        }

    }
  • 相关阅读:
    转:图嵌入 (Graph Embedding) 和图神经网络 (Graph Neural Network)
    转:pytorch框架下—GCN代码详细解读
    图神经网络GNN:给图多个 node features和edge features
    图神经网络GNN:创建图和展示图
    图卷积神经网络GCN:整图分类(含示例及代码)
    转:zip(*args)解压运算
    图卷积神经网络GCN系列二:节点分类(含示例及代码)
    Pycharm远程连接服务器(或者docker)
    认证和授权(Authentication和Authorization)
    HttpContext.Current为NULL
  • 原文地址:https://www.cnblogs.com/meil/p/533838.html
Copyright © 2011-2022 走看看