ASP.NET 服务器控件事件模型

楼主
ASP.NET 服务器控件事件模型
就工作方式而言,ASP.NET 服务器控件引发的事件与传统客户端窗体或基于客户端的 Web 应用程序中的事件稍有不同。这些差异主要是由事件本身与事件处理位置之间的分离导致的。

在基于客户端的应用程序中,事件在客户端引发和处理。而在 Web 窗体页中,与服务器控件关联的事件在客户端引发,但在 Web 服务器上由 ASP.NET 页框架进行处理。

对于在客户端引发的事件,Web 窗体控件事件模型要求在客户端捕获事件信息并通过 HTTP POST 将事件消息传输到服务器。页框架必须解释此传递以确定所发生的事件,然后调用服务器端代码中适当的方法来处理此事件。

[url=../images/upload_mm/2003/04/17/784936562500.bmp][img]../images/upload_mm/2003/04/17/784936562500s.gif[/img][/url]

ASP.NET 实际上处理捕获、传输和解释事件的所有技术细节。当您在 Web 窗体页中创建事件处理程序时,无需考虑如何捕获事件信息以及如何使事件信息在代码中可用这些技术细节。相反,可以通过与在传统客户端窗体中大致相同的方式来创建事件处理程序。尽管如此,Web 窗体页中的事件处理还是有一些应该注意的方面。

内部事件集
由于大多数 Web 窗体事件在处理时都需要一次到服务器的往返行程,所以这些事件可能会影响窗体的性能。因此,服务器控件提供了一个有限的内部事件集(通常仅限于 Click 类型事件)。某些服务器控件支持一个特殊版本的 onchange 事件,该事件在控件的值出现更改时引发。例如,CheckBox Web 服务器控件在用户单击此框时会引发一个更改事件。服务器控件不支持经常发生(并且可能在用户不知道的情况下引发)的事件,如 onmouseover 事件。

注意 某些服务器控件支持一组更高级别的事件。例如,Calendar Web 服务器控件引发一个 SelectionChanged 事件,它是 Click 事件的一个更为抽象的版本。
事件参数
Web 和 HTML 服务器控件事件遵循事件处理程序方法的标准 .NET 框架模式。所有事件都传递两个参数:一个是表示引发此事件的对象的对象,另一个是包含所有事件特定信息的事件对象。第二个参数的类型通常是 System.EventArgs,但对于某些控件则是一种特定于该控件的类型。例如,对于 ImageButton Web 服务器控件,第二个参数的类型是 ImageClickEventArgs,它包含有关用户单击处所在的坐标位置的信息。

Web 服务器控件中的回发和非回发事件
在 Web 服务器控件中,某些事件(通常是 Click 事件)会导致窗体被回发到服务器。HTML 服务器控件和 Web 服务器控件(如 TextBox 控件)中的更改事件将被捕获,但不会立即导致发送。相反,它们会被该控件缓存,直到发送再次发生时为止。然后,当再次在服务器上处理该页时,将引发并处理所有的挂起事件。

注意 如果浏览器支持,验证控件可以使用客户端脚本检查用户输入,而无需到服务器的往返行程。有关详细信息,请参阅 Web 窗体的用户输入验证简介。
在服务器页处理期间,将首先处理事件,处理时没有特定的顺序。当处理完所有更改事件后,就会处理导致发送窗体的 Click 事件。

注意 除非对页事件处理有比较详细的了解,否则不应创建依赖于按特定顺序引发的更改事件的应用程序逻辑。有关更多信息,请参阅回发事件示例。
可以指定更改事件导致窗体发送。支持更改事件的 Web 服务器控件包含 AutoPostBack 属性。当此属性为 true 时,控件的更改事件会导致立即发送窗体,而不等待 Click 事件。例如,默认情况下,CheckBox 控件的 CheckedChange 事件不会导致该页被提交。但是,通过将该控件的 AutoPostBack 属性设置为 true,可以指定当用户单击复选框时,立即将该页发送到服务器进行处理。

注意 若要使 AutoPostBack 属性正常工作,用户的浏览器必须设置为允许脚本撰写。这在大多数情况下是默认设置。但是,有些用户会出于安全方面的原因禁用脚本撰写。有关详细信息,请参阅 ASP.NET 服务器控件和浏览器功能。
冒泡事件
Web 服务器控件(如 Repeater 控件、DataList 控件和 DataGrid 控件)可以包含自行引发事件的按钮控件。例如,DataGrid 控件中的每一行都可以包含一个或多个由模板动态创建的按钮。

不同于每个按钮单独引发一个事件,来自嵌套控件的事件是“冒泡的”——也就是说,这些事件都将发送到容器中。该容器又引发一个带有参数的一般事件,名为 ItemCommand,它的参数使您可以发现是哪个控件引发了初始事件。通过响应此单个事件,可以避免不必要地为子控件编写单独的事件处理程序。

ItemCommand 事件包含两个标准事件参数:一个是引用事件源的对象,另一个是包含事件特定信息的事件对象。

注意 DataGrid 和 DataList Web 服务器控件还支持其他事件,如 EditCommand、DeleteCommand 和 UpdateCommand,它们都是冒泡事件的特例。
对于按钮,可以使用 CommandArgument 属性将一个用户指定的字符串传递到事件处理程序中,以便于确定引发该事件的按钮。例如,在一个 DataList 控件中,按钮引发 ItemCommand 事件。您可以将每个按钮的 CommandArgument 属性设置为不同的值——有可能一个按钮的值为“ShowDetails”而另一个按钮的值为“AddToShoppingCart”,随后在该事件处理程序中捕获这些值。

Web 窗体页中的事件委托
一个事件就是一个消息——实际上就是类似于“某按钮已被单击”的消息。在应用程序中,需要将该消息翻译成代码中的方法调用,如“Button1_Click”。事件消息和特定方法(即事件处理程序)之间的绑定是通过事件委托来实现的。有关更多信息,请参阅事件和委托。

在 Visual Basic 中,可以在事件处理程序声明中使用 Handles 关键字将事件绑定到方法上,如以下示例所示:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
在 Visual C# 中,可以在页面中编写一个显式的事件处理程序委托,类似于如下所示:

private void InitializeComponent()
{  
   this.Load += new System.EventHandler(this.Page_Load);
}
ASP.NET 页框架还支持以一种自动的方式将页事件与方法相关联。如果 Page 指令的 AutoEventWireup 属性设置为 true(或者如果缺少此属性,因为它默认为 true),该页框架将自动调用页事件,即 Page_Init 和 Page_Load 方法。在这种情况下,不需要任何显式的 Handles 子句或委托。

AutoEventWireup 属性的缺点是它要求页事件处理程序具有特定、可预测的名称。这限制了您在为事件处理程序命名时的灵活性。

响应 ASP.NET 服务器控件中的客户端和服务器事件
在很大程度上,您主要会关心在服务器代码中引发的事件。但是,如果对于您的应用程序是适当的,也可以通过编写客户端脚本来处理 ASP.NET 服务器控件的客户端事件。

注意 不能使用 HTML 语法来绑定到 Web 服务器控件的客户端事件,而必须使用代码添加事件绑定属性。有关示例,请参阅下表。
例如,您可能具有已转换为 HTML 服务器控件的 HTML 图像按钮元素。通常,在 Web 窗体页中,您将在服务器代码中处理图像按钮的 Click 事件。但是,您可能还想要使用客户端代码在用户将鼠标移到图像上时更改该图像。可以通过为图像按钮的 onmouseover 事件创建客户端脚本来做到这一点。(在此示例中,假设使用支持 HTML 4.0 的浏览器,例如 Microsoft Internet Explorer 4.0 或更高版本。)

注意 在客户端事件处理程序和服务器端事件处理程序具有相同的事件处理程序名称的情况下,总是首先运行客户端事件处理程序,然后运行服务器事件处理程序。但是,允许这种情况出现会导致混乱,因此强烈建议对命名规则进行一些规划。
处理客户端和服务器代码中的 Click 事件
如果要在客户端和服务器上处理事件,有一个事件会给您带来麻烦,它就是客户端 onclick 事件。之所以会出现问题,是因为所有按钮服务器控件(以及其他 AutoPostBack 属性设置为 true 的控件)都会将页提交到服务器。但是,在 HTML 中,只有少数几个控件本来就会提交窗体:

HTML 提交按钮 (<INPUT type=submit>),即类型设置为 Submit 或 Image 的 HtmlInputButton 控件。
Button Web 服务器控件 (<asp:button>)。
对于其他所有被指定为提交页的控件,会将一个小的客户端脚本写入页中,并在该控件被单击时调用此脚本来提交窗体。因此,这些控件已使用客户端 OnClick 事件来调用此提交脚本。

应用程序和会话事件
除了页和控件事件之外,ASP.NET 页框架为您提供了多种使用事件的方法,这些事件可以在应用程序启动或停止时被引发,也可以在单个用户的会话开始或停止时被引发:

对于所有对应用程序的请求,都将引发应用程序事件。例如,当请求应用程序中的任何 Web 窗体页或 XML Web services 时,都将引发 Application_BeginRequest。该事件使您可以初始化资源,这些资源将用于对应用程序的每一请求。相应的 Application_EndRequest 事件使您有机会关闭或处置用于该请求的资源。
会话事件类似于应用程序事件(会话事件有 Session_OnStart 和 Session_OnEnd 事件),但会话事件由应用程序中每一个唯一的会话引发。当用户第一次从应用程序请求页时开始一个会话;当应用程序显式关闭该会话或当会话超时时结束该会话。

电脑版 Page created in 0.0625 seconds with 4 queries.