3.2 Stages of Page Processing
During Web Forms processing, the page goes through distinct stages, which are illustrated in Figure 3-1. The Web Forms processor calls a corresponding page processing event at each stage.
In ASP pages other than global.asa, you have to write your program logic sequentially because your code is executed in the order in which it appears (termed procedural programming). ASP.NET, on the other hand, features event-driven programming, in which the order of execution of a particular code block is not predetermined. You write a block of code called an event handler that is executed whenever that event occurs.
If you've developed client-side code or have programmed using Visual Basic, you're already familiar with event-driven programming. ASP.NET takes event-driven programming to the server side, encouraging you to structure your programming logic into event handlers. In ASP.NET, the Page object is the representation of your ASP.NET page, and you can write handlers at the page level. ASP, on the other hand, supports only events at the application and session levels.
The Page class inherits all of its important events from the System.Web. UI.Control class, which is the ultimate parent of all server controls. This means that all events described below also apply to both built-in and custom server controls because all of these controls ultimately derive from System.Web.UI.Control.
We'll examine these events in detail. First, however, we'll examine how an event is associated with a particular event handler in Visual Basic .NET and C#.
3.2.1 Handling Events
There are three main techniques for handling events in ASP.NET, one of which takes advantage of ASP.NET's ability to wire up standard event handlers automatically and two of which rely on wiring up event handlers manually.
126.96.36.199 Automatic event wiring
When handling events in a page that consists of a single .aspx page, it is often simplest to create event handlers in the standard objectname_eventname syntax familiar to most Visual Basic programmers. By default, ASP.NET will automatically look for handlers such as Page_Init, Page_Load, Page_PreRender, and Page_UnLoad, and will call them automatically at the appropriate time during page processing.
188.8.131.52 Using AddHandler or += to wire events
One method of wiring up events to event handlers manually is to use the Visual Basic .NET AddHandler statement or the C# += operator to hook up an event to a delegate. Delegates, which are used to create event handlers, are similar to function pointers, but are type-safe. The following code snippets illustrate hooking up an event handler for the Click event of an ASP.NET Button server control named Button1:
// C# Button1.Click += new System.EventHandler(Button1_Click); ' Visual Basic .NET AddHandler Button1.Click AddressOf Button1_Click
In both cases, the code tells ASP.NET where to find the procedure to execute when the Click event (namely, Button1.Click) is fired. If, for some reason, you want to unwire an event handler, you can use the Visual Basic .NET RemoveHandler statement or the C# -= operator to accomplish the reverse of AddHandler and +=.
184.108.40.206 Using the WithEvents and Handles keywords to wire events
Visual Basic .NET developers have a third option for wiring up events: the WithEvents and Handles keywords. The WithEvents keyword precedes the name of a declared control (usually in a code-behind class) and tells ASP.NET that you want to be able to handle the control's events using the Handles keyword. The Handles keyword is appended to the first line of the event handler procedure and is followed by the object name and the name of the event it handles. The syntax of these keywords is shown in the following code snippet. Note the use of the VB line continuation character, which indicates that both the Sub declaration and the Handles keyword should be interpreted as a single line of code:
Protected WithEvents MyButton As New Button Private Sub MyButton_Click(sender As Object, e As EventArgs) _ Handles MyButton.Click 'Event handling code End Sub
3.2.2 ASP.NET Page and Control Events
Each stage of Web Forms processing shown in Figure 3-1 exposes particular events that can be handled in your code. In this section, we'll examine those events in detail.
The Init event, which is fired with each request, is used to initialize the page. If variables need to be declared and initialized before the majority of page processing begins, the event handler for the Init event is the place to do it. A good example of this is that for C# web projects in Visual Studio .NET, the Page_Init event handler is used to wire up other events handled by a page's code-behind class. The Page_Init handler, in turn, is wired up in the constructor for the code-behind class.
The Load event is fired on every request to the page, immediately after all the controls on the page have been initialized. Since this event is fired every time the page is loaded, and if your page is posted to itself (known as a postback), you can use the IsPostBack property of the Page object to write logic that executes only once. For instance, in the code in Example 3-6, you will see the label "Before PostBack" the first time you load the page because, since the page has not been submitted to itself yet, the IsPostBack property is False. When the page is posted back, you will see the label "Posted Back" because the IsPostBack property has become True.
<%@ Page Language="vb" %> <html> <head> <title>IsPostBack Demonstration</title> <script runat="server" > Sub Page_Load(Sender As Object, e As EventArgs) If Not IsPostBack Then lblMessage.Text = "Before PostBack" Else lblMessage.Text = "Posted Back" End If End Sub </script> </head> <body> <h1>Demonstration of IsPostBack property</h1> <form id="frmPostBack" runat="server"> <asp:label id="lblMessage" runat="server"/> <asp:Button type="Submit" text="Post Back" runat="server"/> </form> </body> </html>
The DataBinding event is fired when the page (or a control) is bound to a data source. This will usually occur when the DataBind method of the Page object is called, generally from the Page_Load event handler. The DataBinding event handler can be used to do any special processing related to the data-binding portion of page processing. Databinding is covered in greater detail in Chapter 7.
220.127.116.11 Control events
The control event handlers are identified by an attribute of the control's tag. For example, in the following tag:
<asp:Button id="MyButton" onClick="MyButton_Clicked" runat="server">
the attribute/value pair onClick="MyButton_Clicked" connects the control event (the Click event) with its event handler (the MyButton_ Clicked procedure).
Change events execute only on the next request to the server. For example, if you have written an event handler for the TextBox_Changed event, only when the page is submitted to the server will the code inside the handler be executed. Server-side change events are not the same as the client-side change events that execute instantly.
The most commonly used Change events and the controls that raise these events are listed in Table 3-1.
Action events, unlike Change events, immediately cause the page to be posted back to the server. For example, if you have an event handler for the Command_Click event, the logic inside the handler will be executed as soon as you click that command button (after the page is posted back to the server, of course).
The most commonly used Action events and the controls that raise them are listed in Table 3-2.
The PreRender event is fired just before the page (or control) is rendered and sent to the client. The PreRender event is the last chance for page output to be modified before it is sent to the browser. It is also the last event that fires before the ViewState of the controls on the page is saved, so any control changes you wish to have saved to ViewState should be made either before or during this event. ViewState is discussed more fully in the Section 3.3 in this chapter. The PreRender event is also the last opportunity for registering client-side script blocks using the helper methods of the Page class (such as Page.RegisterClientScriptBlock).
Sub Page_Unload(sender As Object, e As EventArgs ) ' Close the database connection objConnection.Close( ) End Sub