当前位置导航:炫浪网>>网络学院>>网页制作>>ASP.NET教程

ASP.NET表单介绍

  Form(表单)是asp.net开发中重要的组成部分--没有Form就没有asp.net Web编程模型。Form不局限于纯粹的HTML,但是在asp.net中会受到一些限制。对于asp.net页面,Form可以提交自身,并且asp.net模型提供了控件状态管理和postback事件。由于asp.net的单一Form模型使得编写asp.net应用程序简单又便捷.

  asp.net中窗体上的限制可能听起来怪异而武断,但实际上跟asp.net模型有直接的作用。然而,有一种实际情况是asp.net 1.x form 模型所不支持的:在同一个页面拥有多个,互不干涉的form。比如,您不能在某个页面上添加一个搜索文本框并将结果提交到另一个页面.

  在msdn杂志2003年5月刊上,我写了一个专栏关于asp.net 1.x的Form编程(参阅 Cutting Edge: Form-based Programming in asp.net),对于asp.net 2.0的介绍里, 关于提交给不同的页面这一主题的地址有一些变动。本文我将讨论asp.net 2.0下的Form编程.

  ASP.NET表单·窗体呈现

  让我们探索一下asp.net的窗体世界,去了解窗体(包括控件)是如何实际呈现的。在asp.net页面上,< form>标记可以是几种容器控件像< table>, < div>, 或 < body>的子控件; 然而,在大多数页面中,< form>只是简单作为< body>的子节点。如果一个非容器控件(比如TextBox)被放置在form标记之外,将会抛出一个运行时错误(编译时不会对此进行检查)。请看如下代码,节选自TextBox的 AddAttributesToRender 方法:

  protected override void AddAttributesToRender(HtmlTextWriter writer)

  {

  if (this.Page != null)  this.Page.VerifyRenderingInServerForm(this);

  ...

  }

  调用页面的VerifyRenderingInServerForm方法将会处理此工作。(当您自己编写自定义服务器控件时应避免这种行为)

  ASP.NET表单·HtmlForm类

  HtmlForm继承自HtmlContainerControl,使得窗体具有包含子控件的能力。HtmlForm提供了对HTML< form>元素在服务器端的编程访问能力,其properties列表见图1。从表中可以看到asp.net 1.x 和 asp.net 2.0的变化主要限于几个properties。

  一个表单必须拥有唯一的名字,未指定名字时asp.net会自动分配一个。可以通过ID或Name属性给Form设置标识,同时设置时以ID属性优先。可是有一点要注意,一些编程接口使用Name属性来兼容xhtml。在xhtml中,elements通过ID标识而不是Name,因此通常来讲,最好以ID属性为准。

  表单的父对象是一个具有runat属性的总容器控件。如果这样的控件不存在,页面对象被作为父对象。典型的服务器端form的容器是标记为服务器端对象的< table>或< div>。

  图2 列出了HtmlForm类中最常用的到一些方法。这些方法继承于System.Web.UI.Control类。注意FindControl方法只搜索form的直接子控件。内部容器中的子控件和表单子控件的子控件将不能被找到。

  ASP.NET表单·多表单管理

  通常来讲,投入单表单模型的怀抱而放弃对多表单系统的支持并不算是很大的牺牲。尽管一些页面如果能使用multiple forms将会获得更加致一致和自然的设计--至少对于那些包含有一定逻辑关系的输入控件组的表单 例如,一个页面除了要给用户提供信息,还需要支持一个搜索表单或者登录框表单。

  您可以将搜索和登录功能合并到ad hoc类并通过显示信息的同一页面调用,然而这并不是构造代码的最佳方法。

  如果您正在将老的代码移植到asp.net, 您可能觉得将登录和搜索代码置于另一个专门的页面更容易些。可是您如何才能将那些页面的数据提交到本页呢?

  在单表单模型里,页面总是提交自身而且也没有给开发者提供设置回传目标的钩子。对于HTML和ASP编程,表单的Action属性是单一值,在asp.net的HtmlForm类中也不暴露此属性。单表单模型跟asp.net平台整合的太紧密,您要么采用要么放弃——或者,做为一个附加的选择就是可以用ASP的方式编写代码不使用服务器表单。象下面要讲到的,在asp.net 2.0里,可以将数据提交到另一个页面,但是这个特性是通过一些按钮控件的新增功能得以实现的。现在,我们先看看使用HTML的非服务器端表单时有什么棘手问题。

  在asp.net中,当有多个HtmlForm控件需要呈现时将会抛出异常。页面中的第一个HtmlForm控件被呈现后,会有一个布尔标记被设为true,此标记指示了是否有HtmlForm已被呈现,当另一个HtmlForm试图呈现时,由于此标记已经被设置为true因而引发一个异常。

  如果一个Web Form中包含了一个服务器form和任意数量的不含有runat属性的< form>标记不会导致任何错误。没有runat属性,任何标记都成为纯粹单一的HTML而直接呈现

  此页面包含2个表单,第二个是没有ruan="server"属性的HTML表单,因此被asp.net完全忽略。提供给浏览器的html中合法包含了两个< form>元素,它们指向两个不同的action URL。

  然而从功能上来讲此代码有一个大的缺陷:不能使用asp.net编程模型来检索客户端表单action页面上的提交数据。当编写search.aspx时,对于客户端表单的action页面,不能对页面的控件借助视图状态和提交数据来读取和更新它们的状态。(The apparent statefulness of asp.net server controls is obtained by making pages post to themselves)为了知道提交给search.aspx的数据,您必须采取针对ASP模型的直接在回传数据中检索的传统风格:

  protected void Page_Load(object sender, EventArgs e)

  {

  // Use the Request to retrieve posted data

  string textToSearch = Request.Form["Keyword"].ToString();

  ...

  // Use standard asp.net to populate the page UI

  KeywordBeingUsed.Text = textToSearch;

  }

  可以使用 HttpRequest 对象协议规范中的集合(Page.Request等同于HttpContext.Current.Request)来检索回传的数据——对于POST方式时使用Form,GET方式时使用QueryString,或者想要兼容对Form、QueryString、 ServerVariables 和 Cookies的访问时使用Params。HttpRequest 对象会在页面创建前将数据封装,因此,页面的任何事件都可以随意调用Page.Request.对于自提交的asp.net页面,不需要使用Request是由于可以借助于一个强类型的编程模型,但是对于以前,可靠的 HttpRequest 对象依然是需要时为您而备的。

  还有一件有趣的事要注意,当用户点击Search按钮时,search.aspx被调用,它只接受那些Html 表单上发送回来的数据,不会有视图状态被回传,也没有额外的数据传递。如果必须提交数据到另一个页面,使用传统风格仍然是多数高效性能的明智之选。如随后本专栏所述,asp.net 2.0 跨页提交特性传递了相当大的,类视图状态的数据域。

 

相关内容
赞助商链接