虚拟窗体Web自定义控件

分享于 

18分钟阅读

Web开发

  繁體 雙語

介绍

如果是这样,我就会在页面的页眉区域中输入表单字段,如果我在表单字段中双击 cursor,那就是页面上第一个按钮的click事件,它是页面上第一个按钮的click事件。 设置是常见的: 母版页包含带有 runat="server" 属性的form 标记,该窗体包装页面的全部内容。 直到我在注册页面上找到自己,而不是点击 register 按钮,我只是按了输入键。 不是注册我,而是出现了一条消息,说明需要用户名和密码。 因为这些字段也存在于注册表单上,我很困惑,更多时用鼠标点击'register 现在'按钮。 我快速地发现了发生了什么,然后翻翻了我的代码档案,直到我几年前发现了一些 JavaScript,取消默认行为。 我在页面中添加了这个代码段,直到找到另一个具有相同问题的页面。 就是在那时我认为"如果有一个控件- 就像一个面板控件- 可以用来包装一些输入控件,设置一个属性。'点击了'输入输入键时),这就是你所需要做的所有事情。

现在有这样一个控制。

实际上,就像 Onskee1 指出的,标准的ASP Panel 控件具有" DefaultButton"属性,实现类似功能;但是,仅允许你使用 ASP Button 控件作为指定的按钮。 如果要使用 ASP LinkButton 控件或者其他类型的控件作为默认按钮,则不会对你执行任何操作。 因此,如果你是专门使用 Button 控件,我建议你使用该属性。 如果没有,请阅读。

使用代码

根据页面的需要,你可以按页面的方式对控件进行控制,也可以将它的添加到 web.config 文件的<Pages> 部分,使它的可以用于网站( 清单 1 ) 上的任何页面。

清单 1
<pagesenableeventvalidation="true"enableviewstatemac="true"enablesessionstate="true"><controls><addassembly="WilliaBlog.Net.Examples"namespace="WilliaBlog.Net.Examples"tagprefix="WBN"></add></controls></pages>

然后,将控件添加到页面中,以使它的包装输入:

清单 2
<WBN:VirtualFormid="vf1"runat="server"SubmitButtonId="Button1"UseDebug="false"> 
 <asp:TextBoxID="TextBox1"runat="server"></asp:TextBox><asp:ButtonID="Button1"runat="server"Text="Button1"OnClick="Button1_Click"/></WBN:VirtualForm>

如清单 2所示,你应该使用按钮( 这将被虚拟窗体控件自动转换为客户端标识)的服务器端 ID。 测试它。

使用指导

真正的服务器端虚拟表单web定制控件非常简单。 它继承 System.Web.UI.WebControls.Panel 并包含一个属性,允许你在按下Enter键时设置要按下的Button 或者 LinkButton的ID。 我选择将JavaScript文件嵌入到DLL中,以便移植。 我希望我们在master文件中添加文件,但这对web应用程序的任何低带宽用户都不利,因为它可能会影响web应用程序的任何低带宽用户。"。 为此,我使用 YUI 压缩器插件去除所有注释和额外空白,并在DLL中包含了两个脚本版本。 在将属性 UseDebug 设置为 true 时,它将使用长冗长版本,这使得在firebug中进行调试更加容易,但是当你将该属性从控件声明中删除或者将它的设置为 false 时,可以使用压缩版本。

要使文件可以从控件的控件中访问,只需将文件添加到项目中,转到属性窗格。 要向web请求公开文件,你需要在清单2 中添加代码 7行和 8 below。 这些条目公开嵌入资源以便 ClientScriptManager 既可以访问文件,也可以知道它是什么类型的文件。 你还可以这种方式嵌入 CSS。图像和其他类型的文件。 注释:项目名称空间( 如项目页属性的应用程序选项卡中定义的那样)的默认值需要作为前缀添加到嵌入资源的文件名中。

因此,除了公开这些属性,所有控件实际上只是重写 onPreRender 事件并在页面中插入一些 JavaScript。 清单1 到 79的第 3行将链接注入到嵌入式JavaScript文件中,它显示在页面源中,如下所示:

<scriptsrc="/WebResource.axd?d=j246orv_38DeKtGbza6y6A2&amp;t=633439907968639849"type="text/javascript"></script>

然后,动态生成一个脚本来创建虚拟表单对象的一个新实例,传递 VirtualForm 服务器控件的on和 register。

清单 3
1 using System; 
 2 using System.Collections.Generic; 
 3 using System.ComponentModel; 
 4 using System.Text; 
 5 using System.Web; 
 6 using System.Web.UI; 
 7 using System.Web.UI.WebControls; 
 8 
 9 // Script Resources  10 [assembly: WebResource("WilliaBlog.Net.Examples.VirtualForm_Debug.js", 
 "text/javascript")] 
 11 [assembly: WebResource("WilliaBlog.Net.Examples.VirtualForm_min.js", 
 "text/javascript")] 
 12 
 13 namespace WilliaBlog.Net.Examples 
 14 { 
 15 
 16 [ToolboxData("<{0}:VirtualForm runat="server"></{0}:VirtualForm>")] 
 17 publicclass VirtualForm : System.Web.UI.WebControls.Panel 
 18 { 
 19 [Bindable(true), DefaultValue("")] 
 20 publicstring SubmitButtonId 
 21 { 
 22 get 
 23 { 
 24 string s = (string)ViewState["SubmitButtonId"]; 
 25 if (s == null) 
 26 { 
 27 returnstring.Empty; 
 28 } 
 29 else 
 30 { 
 31 return s; 
 32 } 
 33 } 
 34 set { ViewState["SubmitButtonId"] = value; } 
 35 } 
 36 
 37 [DefaultValue(false)] 
 38 publicbool UseDebug 
 39 { 
 40 get 
 41 { 
 42 string s = (string)ViewState["UseDebug"]; 
 43 if (string.IsNullOrEmpty(s)) 
 44 { 
 45 returnfalse; 
 46 } 
 47 else 
 48 { 
 49 return s.ToLower() == "true"; 
 50 } 
 51 } 
 52 set { ViewState["UseDebug"] = value; } 
 53 } 
 54 
 55 public VirtualForm() : base() { } 
 56 
 57 protectedoverridevoid OnPreRender(System.EventArgs e) 
 58 { 
 59 if (!string.IsNullOrEmpty(this.SubmitButtonId)) 
 60 { 
 61 Control theButton = this.FindControl(this.SubmitButtonId); 
 62 if ((theButton!= null)) 
 63 { 
 64 string resourceName; 
 65 if (this.UseDebug) 
 66 { 
 67 resourceName = 
 "WilliaBlog.Net.Examples.VirtualForm_Debug.js"; 
 68 } 
 69 else 
 70 { 
 71 resourceName = "WilliaBlog.Net.Examples.VirtualForm_min.js"; 
 72 } 
 73 
 74 ClientScriptManager cs = this.Page.ClientScript; 
 75 
 76 string scriptLocation = 
 cs.GetWebResourceUrl(this.GetType(), resourceName); 
 77 if (!cs.IsClientScriptIncludeRegistered("VirtualFormScript")) 
 78 { 
 79 cs.RegisterClientScriptInclude("VirtualFormScript", 
 scriptLocation); 
 80 } 
 81 
 82 // New script checks for"Sys" Object, if found// events will be rewired after updatepanel refresh.  83 StringBuilder sbScript = new StringBuilder(333); 
 84 sbScript.AppendFormat("<script type="text/javascript">{0}", 
 Environment.NewLine); 
 85 sbScript.AppendFormat("//Ensure postback works after" + 
 "update panel returns{0}", 
 Environment.NewLine); 
 86 sbScript.AppendFormat(" function" + 
 "ResetEventsForMoreInfoForm() {{{0}", 
 Environment.NewLine); 
 87 sbScript.AppendFormat(" var vf_{0} = new WilliaBlog.Net." + 
 "Examples.VirtualForm(" + 
 "document.getElementById" + 
 "('{0}'),'{1}');{2}", this.ClientID, 
 theButton.ClientID, Environment.NewLine); 
 88 sbScript.AppendFormat(" }}{0}", Environment.NewLine); 
 89 sbScript.AppendFormat(" if (typeof(Sys)!=="undefined"){{{0}", 
 Environment.NewLine); 
 90 sbScript.AppendFormat(" Sys.WebForms.PageRequestManager." + 
 "getInstance().add_endRequest(" + 
 "ResetEventsForMoreInfoForm);{0}", 
 Environment.NewLine); 
 91 sbScript.AppendFormat(" }}{0}", Environment.NewLine); 
 92 sbScript.AppendFormat(" var vf_{0} = new WilliaBlog.Net." + 
 "Examples.VirtualForm(document.getElementById('{0}'),'{1}');{2}", 
 this.ClientID, theButton.ClientID, Environment.NewLine); 
 93 sbScript.AppendFormat("</script>"); 
 94 
 95 string scriptKey = string.Format("initVirtualForm_" + 
 this.ClientID); 
 96 
 97 if (!cs.IsStartupScriptRegistered(scriptKey)) 
 98 { 
 99 cs.RegisterStartupScript(this.GetType(), scriptKey, 
 sbScript.ToString(), false); 
 100 } 
 101 } 
 102 } 
 103 base.OnPreRender(e); 
 104 } 
 105 } 
 106 }

JavaScript

当然,大部分代码是 JavaScript。 从到 62行只创建 WilliaBlog 名称空间,我从中将它'借来'! 用户界面库( YUI )。 iPhone 7 还没出来,我们已经在iPhone上获取细节 8,或者不管是想到下一步。 WilliaBlog.Net.Examples.VirtualForm 对象从第 65行开始。 实际上,它循环遍历父 Div ( 这里 Div的ID作为参数传递给构造函数) 中的每个输入控件( 行 159 -164行),并为每个输入控件分配 onkeypress 事件( handleEnterKey )。 除了输入键之外,所有其他按键都透明传递,但是一旦检测到,就会取消默认行为,而调用 submitVirtual 函数将被取消。 函数只是检查你提供的按钮是输入( 图像或者提交按钮) 还是锚定( 超链接或者链接按钮),通过调用前面的click() 方法或者导航到 href 属性。 实际上,removeEventstopEvent 方法并不被调用,但是我将它们包括在了。

清单 4
 1 /*********************************************************************
 2 * 
 3 * File : VirtualForm_Debug.js 
 4 * Created : April 08 
 5 * Author : Rob Williams 
 6 * Purpose : This is the fully annotated, easy to understand
 and modify version of the file, 
 however I would recommend you use 
 7 * something like the YUI Compressor 
 (http://developer.yahoo.com/yui/compressor/) to minimize load time. 
 8 * This file has its Build Action Property set to"Embedded Resource" 
 which embeds the file inside the dll, so we never have to 
 9 * worry about correctly mapping a path to it. 
 10 * 
 11 **********************************************************************/ 
 12 
 13 if (typeof WilliaBlog == "undefined" ||!WilliaBlog) { 
 14 /** 
 15 * The WilliaBlog global namespace object.
 * If WilliaBlog is already defined, the 
 16 * existing WilliaBlog object will not be overwritten so that defined 
 17 * namespaces are preserved. 
 18 * @class WilliaBlog 
 19 * @static 
 20 */ 
 21 var WilliaBlog = {}; 
 22 } 
 23 
 24 /** 
 25 * Returns the namespace specified and creates it if it doesn't exist 
 26 * <pre> 
 27 * WilliaBlog.namespace("property.package"); 
 28 * WilliaBlog.namespace("WilliaBlog.property.package"); 
 29 * </pre> 
 30 * Either of the 上面 would create WilliaBlog.property, then 
 31 * WilliaBlog.property.package 
 32 * 
 33 * Be careful when naming packages. Reserved words may work in some browsers 
 34 * and not others. For instance, the following will fail in Safari: 
 35 * <pre> 
 36 * WilliaBlog.namespace("really.long.nested.namespace"); 
 37 * </pre> 
 38 * This fails because"long" is a future reserved word in ECMAScript 
 39 * 
 40 * @method namespace 
 41 * @static 
 42 * @param {String*} arguments 1-n namespaces to create 
 43 * @return {Object} A reference to the last namespace object created 
 44 */ 
 45 WilliaBlog.RegisterNamespace = function() { 
 46 var a=arguments, o=null, i, j, d; 
 47 for (i=0; i<a.length; i=i+1) { 
 48 d=a[i].split("."); 
 49 o=WilliaBlog; 
 50 
 51 // WilliaBlog is implied, so it is ignored if it is included  52 for (j=(d[0] == "WilliaBlog")? 1 : 0; j<d.length; j=j+1) { 
 53 o[d[j]]=o[d[j]] || {}; 
 54 o=o[d[j]]; 
 55 } 
 56 } 
 57 
 58 return o; 
 59 }; 
 60 
 61 //declare the 'WilliaBlog.Net.Examples' Namespace  62 WilliaBlog.RegisterNamespace("WilliaBlog.Net.Examples"); 
 63 
 64 //declare Virtual Form Object  65 WilliaBlog.Net.Examples.VirtualForm = function(formDiv,submitBtnId) 
 66 { 
 67 this.formDiv = formDiv; //The id of the div that represents our Virtual Form  68 this.submitBtnId = submitBtnId;
 //The id of the button or Linkbutton that should be clicked when pushing Enter  69 
 70 // When using these functions as event delegates the// this keyword no longer points to this object as it is out of context  71 // so instead, create an alias and call that instead.  72 var me = this; 
 73 
 74 this.submitVirtual = function() 
 75 { 
 76 var target = document.getElementById(me.submitBtnId); 
 77 //check the type of the target: If a button then call the click method.  78 if(target.tagName.toLowerCase() === 'input') 
 79 { 
 80 document.getElementById(me.submitBtnId).click(); 
 81 } 
 82 //If a link button then simulate a click.  83 if(target.tagName === 'A') 
 84 { 
 85 window.location.href = target.href; 
 86 } 
 87 }; 
 88 
 89 this.handleEnterKey = function(event){ 
 90 var moz = window.Event? true : false; 
 91 if (moz) { 
 92 return me.MozillaEventHandler_KeyDown(event); 
 93 } else { 
 94 return me.MicrosoftEventHandler_KeyDown(); 
 95 } 
 96 }; 
 97 
 98 //Mozilla handler (also Handles Safari)  99 this.MozillaEventHandler_KeyDown = function(e) 
 100 { 
 101 if (e.which == 13) { 
 102 e.returnValue = false; 
 103 e.cancel = true; 
 104 e.preventDefault();
 // call the delegate function that// simulates the correct button click  105 me.submitVirtual();
 106 returnfalse; 
 107 } 
 108 returntrue; 
 109 }; 
 110 
 111 //IE Handler  112 this.MicrosoftEventHandler_KeyDown = function() 
 113 { 
 114 if (event.keyCode == 13) { 
 115 event.returnValue = false; 
 116 event.cancel = true; 
 // call the delegate function that simulates// the correct button click  117 me.submitVirtual();
 118 returnfalse; 
 119 } 
 120 returntrue; 
 121 }; 
 122 
 123 this.addEvent = function(ctl, eventType, eventFunction) 
 124 { 
 125 if (ctl.attachEvent){ 
 126 ctl.attachEvent("on" + eventType, eventFunction); 
 127 }elseif (ctl.addEventListener){ 
 128 ctl.addEventListener(eventType, eventFunction, false); 
 129 }else{ 
 130 ctl["on" + eventType] = eventFunction; 
 131 } 
 132 }; 
 133 
 134 this.removeEvent = function(ctl, eventType, eventFunction) 
 135 { 
 136 if (ctl.detachEvent){ 
 137 ctl.detachEvent("on" + eventType, eventFunction); 
 138 }elseif (ctl.removeEventListener){ 
 139 ctl.removeEventListener(eventType, eventFunction, false); 
 140 }else{ 
 141 ctl["on" + eventType] = function(){}; 
 142 } 
 143 }; 
 144 
 145 this.stopEvent = function(e) 
 146 { 
 147 if (e.stopPropagation){ 
 148 // for DOM-friendly browsers  149 e.stopPropagation(); 
 150 e.preventDefault(); 
 151 }else{ 
 152 // For IE  153 e.returnValue = false; 
 154 e.cancelBubble = true; 
 155 } 
 156 }; 
 157 
 158 //Grab all input elements within virtual form (contents of a div with divID)  159 this.inputs = this.formDiv.getElementsByTagName("input"); 
 160 
 161 //loop through them and add the keypress event//to each to listen for the enter key  162 for (var i = 0; i <this.inputs.length; i++){ 
 163 this.addEvent(this.inputs[i],"keypress",this.handleEnterKey); 
 164 } 
 165 }

历史记录

  • v1.0.

WEB  控制  for  form  Virtual  custom-control  
相关文章