多 < form> 标记
如果多个服务器端form出现在同一个web form上,将抛出异常。不易发现并不为人知的是,事实上web form可以包含任意数量的服务器端form,只要同一时刻仅有一个可见并呈现。例如,一个页面包含有3个带有runat="server"标记的< form>是允许的,但是仅有一个form的Visible属性可以设置为true.通过激活HtmlForm类的Visible属性,您可以在页面的生命周期改变活动的服务器端form。这个小窍门不能解决同时有多个活动form的问题,但是有时还是有所帮助的。
让我们考虑一下图4中的页面,所有的< form>被标记为runat="server",但是只有第一个是可见的,互斥的form在asp.net 1.x中很顺利的实现了一个向导。通过在按钮事件中转换各form的可见性,您可以获得一个类向导的行为,参看图5:

ASP.NET表单:类向导页面的运行效果
这个技巧在asp.net 2.0中基本没用,因为您会发现有2个新控件:MultiView 和 Wizard。MultiView控件使用逻辑等同的互斥表单,可惜它使用panel而没用正统的form。MultiView允许你定义多个互斥的HTML panel,并提供了API来切换这几个panel的可见性,并确保同一时刻只有一个被激活并可见。MultiView控件没有提供内建的用户接口。Wizard控件仅是MultiView加上一个类向导的预定义的UI块,我在MSDN杂志2004年11期上讲解过它(参阅 Cutting Edge: The asp.net 2.0 Wizard Control )。
ASP.NET表单·Cross-Page Posting(跨页提交)
asp.net 2.0 提供了一个新的内建进制以覆盖常规处理周期并允许页面提交到另一个页面。通常,postback发生在下面两种方式之一:Submit按钮激发或通过script激发。典型的按钮提交自动指向form指定的提交地址,而如果提交是通过script时则更加灵活机动。在asp.net 2.0中,您可以配置某个控件(尤其那些实现了新的IButtonControl接口的)使其可以提交给其他目标页面,具体可以查阅cross-page posting。
实现IButtonControl的核心控件是Button, ImageButton, 和 LinkButton。通常,通过实现IButtonControl,所有的自定义控件都可以有表单中的按钮同样的效果。IButtonControl接口正是一个asp.net从1.0到2.0迁移时代码重构的一个典型例子。IButtonControl接口聚合了asp.net 1.x支持的多数按钮控件(包括一些html按钮控件)的一些属性。另外,一些新的属性公布了新增的功能,象PostBackUrl 和 ValidationGroup,图6详细描述了IButtonControl接口。接下来的代码片断演示了如何使用:
当PostBackUrl属性被设置,asp.net运行时为按钮控件的相应的html元素绑定一个新的JavaScript功能。将会使用新的WebForm_DoPostBackWithOptions函数取代常规我们使用的__doPostback函数,客户端呈现效果如下:
结果是,当用户点击按钮时,当前的表单提交内容给指定的目标页。那么视图状态的情况呢?当含有可以cross-page posting的控件时,页面会创建一个name为__PREVIOUSPAGE的隐藏域,此域包含了提交页的信息。目标页使用此信息来创建一个完整状态的引用来调用页对象。
在目标页,您可以使用Page类的新增的一个属性PreviousPage来引用提交页和页面上所有的控件。下面是目标页面对form中某TextBox内容检索的后台代码:
protected void Page_Load(object sender, EventArgs e)
{
// Retrieves some posted data
TextBox txt = (TextBox) PreviousPage.FindControl("TextBox1");
...
}
通过使用Page类的PreviousPage属性,可以访问提交页上声明的任意输入控件.对输入控件的访问是弱类型的并间接使用FindControl方法.摆在事实面前的问题是目标页面并不知道关于提交页类型的任何信息.同样地,它也不能提供对源页面类的指定成员的访问.
此外,注意FindControl仅仅查找当前container中的控件,如果你要找的控件是在另一个控件内部(比如模板),您必须首先取得这个container的引用然后再搜索container来查找那个控件.为了避免完全借助FindControl,还需要另一种途径.
为了检索提交页面上的的值,FindControl将仅提供安全的选项当您预先不知道将会调用哪个目标页时.然而,当在应用程序的上下文中使用cross-page posting时,将有机会确切知道的是谁将调用和如何调用这个页面.这种情况下,您可以利用PreviousPageType指令使目标页的PreviousPageType属性强类型为源页面类.在目标页,添加下面的指令:
指令可以为两个互斥属性之一:VirtualPath 或 TypeName.VirtualPath指提交页的URL,TypeName则指明调用页的类型.PreviousPageType指令使目标页PreviousPage属性返回给定路径上的页面相同类型(或者TypeName属性指定的类型)的一个对象引用,而事实本身是您不能直接访问输入控件.在asp.net中,每个页面类包含了子控件对应的protected成员.不幸的是,您不能调用外部类的受保护成员.事实上,只有派生类可以访问父类的受保护成员.
为了达到这个目的,您必须在调用页上在一个public属性来进行提交页信息的访问.例如,假象crosspostpage.aspx页上包含一个名字为_textBox1的TextBox,为了使它能够在目标页访问,必须在后台类增加如下代码:
public TextBox TextBox1
{
get { return _textBox1;
}
}
作为cross-page调用潜在可能的目标,不会自动将目标页成为别的类型.通常目标页总是被自身调用,例如通过一个超链接.这种情况发生时PreviousPage属性返回null并且别的回传相关的属性(象IsPostBack)采用常规值.对于双重功能的页面,好的办法是添加额外的代码来分辨页面的行为.下面的Page_Load事件中的代码使页面只工作于cross-page调用方式:
if (PreviousPage == null)
{
Response.Write("Sorry, that's not the right way to invoke me.");
Response.End();
return;
}
ASP.NET表单·页面重定向
除了按钮控件的PostBackUrl属性,asp.net提供了另一个页面间传递控件和值的机制:Server.Transfer方法.当你调用此方法,新页面的URL不会反映到浏览器的地址栏,因为这种页面转向发生服务器端--在客户端不会有任何间接事件发生.下面的代码演示了如何使用此方法来进行页面定向:
protected void Button1_Click(object sender, EventArgs e)
{
Server.Transfer("targetpage.aspx");
}
注意下面对页面中进行重定向的调用代码不会被执行.最后,Transfer只是页转向的方法.可是,却对两种情况十分有效:第一,客户端的请求.例如,使用Response.Redirect.第二,同一个应用程序中某请求要在新的页面请求被重用.
对于asp.net 1.x,可以通过使用http上下文的Handler属性获取调用对象,象下面所示:
Page caller = (Page) Context.Handler;
由于Handler属性返回了一个有效的对象引用,主体页可以访问它的public成员,但是象我们上面讨论过的不能直接访问页面上受保护级别的控件.
本编程模型也使用于asp.net 2.0, 不过,在 asp.net 2.0中,变得更简单了,不再需要使用Handler.你可以使用与cross-page postings相同的编程模型并借助一个非空的PreviousPage属性和强类型访问输入域的@PreviousPageType指令来处理.那么页面如何才能检测它是被server transfer调用还是cross-page postback?两种方式下PreviousPage都是非空的,但是PreviousPage对象的Page.IsCrossPagePostBack在cross-page posting方式是为true,而erver transfer则为false.
小结
从一个页面传值到另一个页面有很多种方法可以达成--cross-page posting,server transfer,HTML forms, cookies, session-state, query strings, 或者其他方法等等.那么最有效的是哪个呢?在 asp.net 2.0中,cross-page posting 和 server transfer提供了一个常见的编程模型,但却潜在地通过View State移动了大块的数据。而这些信息是否真正需要依赖于目标页面的描述。在很多情况下,目标页面仅仅需要接收启动运作的一些参数。if this is so,HTML客户端表单可能用移动数据更加有效,尽管HTML表单需要一个类ASP的编程模型。
asp.net 2.0为HtmlForm类增加了一些新的特性,然而核心行为并未改变,因此提交自身仍是asp.net编程的主要方法。您可以混合客户端form和服务器form,也可以拥有多个服务器form不过同一时间内仅有一个可见。
- 上一篇:ASP.NET MVC分页控件的实现
- 下一篇:没有了

百鸣[Baiming.org]欢迎您~