Pages, Controls, and Data

I l @ ve RuBoard

Now that you've learned how to create Web Forms and other ASP.NET pages, let's look in more detail at the Page class, its life cycle, and how to use controls in conjunction with a Page .

The Page Class

Every ASP.NET page has an associated Page class. This class can be created from an ASPX page that contains a mixture of HTML and code, or it can be formed from the merger of automatically generated code and a code-behind class (as described earlier). In either case, the attributes of the <%@ Page %> directive provide some key information when this class is created, as shown in Table 16-1.

Table 16-1. Important Attributes of the <%@ Page %> Directive

Page Attribute

Description

Language

The default language for the page.

Inherits

Defines the class that this page should extend ”usually the code-behind class associated with the page. The run ­time will search for this class in local assemblies stored in the bin directory under the directory in which the page resides, and then in any assemblies in the search path that are explicitly included in this page, and finally in assemblies in the GAC. If this search proves fruitless, the file defined with the Src attribute will be located and compiled.

Src

Defines the name of the source file that holds the code-behind class for this page. Because .NET provides for cross-language inheritance, the code that makes up the page can be defined in any language supported by the common language runtime.

Transaction

Indicates whether the page is transactional and, if so, how transactions should be handled (as described later).

ErrorPage

Defines a page that will be displayed if an unhandled exception occurs (as described later).

ContentType

Sets the content type to be returned to the client in the HTTP response header. If you're generating XML rather than HTML, you should set this to "text/xml" .

EnableSessionState

Indicates whether the page is part of a session and has session state available to it (as described later).

EnableViewState

Indicates that the user interface state should be maintained between round-trips to the server when the same page is displayed multiple times (typically using a hidden field called __VIEWSTATE to maintain the association between the page and its state, as described earlier).

Each page can have only one <%@ Page %> directive, but it can appear anywhere on the page. This differs from ASP, where all directives must be on the first line.

Intrinsic Objects and Properties

As in ASP, certain HTTP- related functionality is available through the properties and methods of the Page class in ASP.NET. ASP employs the concept of intrinsic objects that are abstractions of important underlying concepts, including

  • Request

    A System.Web.HttpRequest object that contains the HTTP information for the current request, including the fields from the HTTP header, such as the cookies, client browser, and type of request ( GET or POST ). If the request is a GET , parameters passed in are available as name/value pairs in the collection retrieved from the QueryString property. Alternatively, if the request is a POST , you can retrieve a System.IO.InputStream from the InputStream property and then read the data from the POST body. If the information sent by the client is form data, you can retrieve a collection of contents of the forms on the page as the name/value pairs from the Form property. Server-side information is also available, such as whether the user is authenticated ( IsAuthenticated property) and information about the virtual and physical path associated with this request.

  • Response

    A System.Web.HttpResponse object through which you can send information back to the client. You can use this object to access the HTTP header fields in the response to set cookies on the client and manipulate other HTTP headers such as the StatusCode . You can write data to the client using the Write or WriteFile methods, or you can obtain the TextWriter stored in the Output property and use that directly (or wrap it in another form of stream). When you've finished writing, you should call the Flush and Close methods on the Response . Output from an ASP page can be cached, ensuring that all of the output is sent to the client. You can also use the Redirect method to inform the client application (the browser) that it should go to another page.

  • Server

    An instance of the System.Web.HttpServerUtility class through which you can access server-related functionality. This includes methods to retrieve the last error message ( GetLastError ), encode and decode HTML-encoded or URL-encoded strings ( Html ­Encode , HtmlDecode , UrlEncode , UrlDecode ), and map a raw filename to one relative to the current virtual directory ( MapPath ). You can use Transfer to redirect the current request directly to another page (rather than using Response.Redirect ), or you can Execute another page and capture its output.

  • Session-scope and application-scope storage

    You can access the session-scope and application-scope storage for this Page instance using its Session and Application properties (as discussed later).

The Page class also provides a Controls collection property that allows programmatic access to the child controls of the page. Some of the information set using the <%@ Page %> directive is also accessible programmatically, such as the ErrorPage property. You can change such properties as the context of your application changes.

Note

If you're not subclassing the Page class, you can access the intrinsic objects using the HttpContext object. Simply call the static HttpContext.get_Current method to retrieve your HttpContext .


Events and Life Cycle

The Page class has certain events that fire during its life cycle. All of the events generated by a Page are inherited from the Control or TemplateControl classes. (The Page is just a specialized form of Control .) The most commonly used ones are the Load and Unload events. In FeedsHowMany.aspx.jsl (version 2), you might have noticed the InitializeComponent method:

 privatevoidInitializeComponent() { this.Calculate.add_Click(newSystem.EventHandler(this.Calculate_Click)); this.add_Load(newSystem.EventHandler(this.Page_Load)); } 

Visual Studio .NET uses the InitializeComponent method to connect events to event handlers for the page (the same technique and method used for Windows Forms applications). As you can see, in this example two event handlers are hooked up, one for the Load event on this (the current Page instance) and one for the Click event on the Calculate Button . A System.EventHandler delegate is added to the list of delegates stored in the Load event through the add_Load call. This EventHandler refers to the Page_Load method, which you can use to perform page-specific initialization:

 privatevoidPage_Load(System.Objectsender,System.EventArgse) { //Initializationhere... } 

In this case, the event handlers are programmatically associated with events. ASP.NET also supports a feature called automatic event wire-up . This takes the form of a property on the <%@ Page %> directive called Auto ­EventWireup . If AutoEventWireup is set to true (the default, if not explicitly defined), the ASP.NET runtime will look for standard method names (such as Page_Load or Page_Init ) that match the events for this page and automatically invoke them when that event occurs, regardless of any event hookups. This is convenient if you can use the standard method names, but don't use it in conjunction with manual hookups of the same events to the same handlers because this will cause the handler to be invoked twice.

Note

By default, Visual J# .NET sets AutoEventWireup to false and connects events to event handlers in the InitializeComponent method, as previously shown.


The Load event is triggered every time the page is loaded. Note that an instance of the page is loaded and unloaded for every client request. The Page instance is used for the duration of that request and is then discarded. This means that instance data will not be retained between invocations. For example, if you wanted to keep a count of the number of times a page has been visited by a client, you could add a counter that's displayed using a Label :

 protectedSystem.Web.UI.WebControls.LabelCount; privateintcount=0; privatevoidPage_Load(System.Objectsender,System.EventArgse) { Count.set_Text("Count: " +++count); } 

Unfortunately, this would display 1 every time you accessed it because the value of the count variable would be thrown away every time the page was unloaded. If you want to maintain state between client requests , you should use the instance of System.Web.SessionState.HttpSessionState provided through the Page object's Session property. This is discussed in detail later in the chapter.

The life-cycle events on an ASP.NET page exhibit a minor side-effect when you work with Web Forms. Web Forms pages post their data back to themselves , and some of the processing of this data might be performed in the Load event handler. But this handler is called every time the page is loaded ”even the first time, before the user has had a chance to fill out the form. Any tasks that are based on the content of the form should not be performed until the user has submitted some information. To get around this, the Page class has an IsPostBack property that tells you whether the current page is being loaded and processed as the result of a form being posted to it or whether this is the initial display of the form. You can use this property to prevent form-based code from being executed the first time a Web Form is called:

 privatevoidPage_Load(System.Objectsender,System.EventArgse) { if(this.get_IsPostBack()) { //Eventcalledastheresultofapostback. //Processthecontentsoftheform } } 

Common Controls

When you use Web Forms to create user interfaces, you need various types of controls that the user can interact with. You've seen that two types of server-side controls are available for building interfaces ”HTML controls and Web controls. Web controls are the more powerful mechanism and are the standard type of control used in most ASP.NET applications. In Visual Studio .NET, you can drag Web controls from the Toolbox onto the design area for your page, set their properties, and set handlers for any events that they might raise. The Web controls can be found in the System.Web.UI.WebControls namespace.

You've already learned how to build a simple user interface using Button , TextBox , and Label controls. This section takes a brief tour of some of the other common controls you might want to use. (This is by no means an exhaustive list!)

Forms and Selection

You can use various server-side controls as part of a form to allow a user to enter information, select options, or indicate actions, including:

  • TextBox

    A field in which a user can type text. A text box can be multiline or read-only or can display password-style asterisks instead of echoing the text typed. This can be hooked up to a server-side event that is triggered when text is entered.

  • Button

    A standard button that can be connected to a server-side event that's triggered when the button is clicked.

  • ImageButton

    A button represented by an image. This can be hooked up to a server-side event that's triggered when the button is clicked.

  • CheckBox

    A standard single selectable check box that can be hooked up to a server-side event that's triggered when the box is selected.

  • CheckBoxList

    A set of selectable check boxes that can be connected to a server-side event that's triggered when any of the boxes are selected.

  • DropDownList

    A standard drop-down list containing a set of elements. This can be hooked up to a server-side event that's triggered each time the user selects a different element from the list.

  • ListBox

    A multiple-item display that can allow one or more items to be selected. This can be hooked up to a server-side event that is triggered when the selection changes.

  • RadioButton

    A single, selectable radio-style button that can be connected to a server-side event that's triggered when the button is selected.

  • RadioButtonList

    A group of selectable radio buttons that are mutually exclusive so that only one can be selected at any time. This can be hooked up to a server-side event that's triggered each time the user selects a different button in the list.

  • HyperLink

    A regular hyperlink with an associated URL.

For more information about these controls, see the .NET Framework documentation.

Displaying Information

You can choose from a selection of controls for displaying information to the user. They include

  • Label

    A placeholder that can contain text and can be positioned in any location on the form. Use Label controls to display text to the user instead of the Response.Write method ”it provides greater control over the positioning and format of the result.

    Tip

    As a general rule, when you use Web Forms, avoid using the Response.Write method.


  • Literal

    A placeholder for the display of text. This cannot be positioned in the way that a Label can.

  • Image

    An image with alternative text for browsers that have image display disabled.

  • Table

    A control for generating an HTML table. You use TableCell and TableRow controls in conjunction with the Table control.

  • Repeater

    A control that repeats a provided output template and populates it based on a data source.

  • DataList

    Similar to, but more powerful than, the Repeater control. It allows you to repeat a template, populating it with data from an ADO.NET data source, and edit the data.

  • DataGrid

    A control for displaying data from an ADO.NET data source in a table that can be selected, sorted, and edited.

  • XmlControl

    A control for displaying some or all of an XML document. Its primary purpose is to allow you to display the result of an XSLT transformation of the XML.

For more information about these controls, see the .NET Framework documentation.

Controlling Layout

When you define an ASP.NET page, you can choose between relative and absolute positioning of controls. Relative positioning uses something called flow layout , which places the controls next to each other across the page. If the combined width of the controls is greater than the width of the page, the layout will "flow" to a new row underneath, until all of the controls are visible. If the user resizes the form at run time, the positions of the controls will be adjusted automatically so none of them is truncated or hidden. This layout works on the same principle as the FlowLayout in the Abstract Window Toolkit (AWT).

The alternative is to use a grid layout , which is the default for Web Forms. This layout allows you to position controls in a precise location, but if a user resizes the form at run time, controls might disappear from view. You can set the type of layout used by changing the pageLayout property associated with that page in Visual Studio .NET.

Note that some controls, such as Literal controls, will not position themselves in a grid layout. In this case, you can add a Panel control to the grid and then place the offending controls within the Panel . This mechanism is also useful for user controls (described next).

Creating Your Own Controls

The standard functionality of ASP.NET Web Forms is powerful, but it doesn't always meet application-specific requirements. If necessary, you can create your own controls for use in your ASP.NET application. You can create your own server-side controls that you can use in the same way as those provided with the .NET Framework, but the details (although not rocket science) are beyond the scope of this chapter. If you have an application requirement for a slightly specialized version of an existing control, however, or for a common group of controls that can be used in multiple places (such as a navigation bar with multiple buttons, images, and labels), a user control might be the answer.

Creating a User Control

A user control consists of one or more Web controls placed in an instance of the System.Web.UI.UserControl class. You can create a user control in Visual Studio .NET by selecting Web User Control in the Add New Item dialog box. (There are other ways to create user controls, which you can pursue by referring to the .NET Framework documentation.) You'll see a design area similar to that for a Web Form. You can add controls as needed to create your user control. If you want to add custom code to your user control, you can access the code-behind and add methods as appropriate.

For example, suppose you want to create a navigation bar for the Fourth Coffee online store. It will contain a label for the Fourth Coffee Web site and several navigation buttons for Home, Back, and so forth. You can start by creating a user control in Visual Studio .NET. Choose the Add Web User Control option from the Project menu. By default, the user control uses a flow layout, so to obtain more precise positioning, you can drag and drop a GridLayoutPanel from the HTML section of the ToolBox onto the design surface of your user control and then resize it as appropriate. You can then drag and drop your Web controls, such as buttons, labels, and images, onto the GridLayoutPanel and add their event-handling code as appropriate. One of these buttons can be a Help button that takes the user to a page containing context-sensitive help. The target URL for this button would have to change from page to page because the context would change. The easiest way to do this is to provide a property, such as HelpUrl , on your user control class, as shown in the sample file Navigation.ascx.jsl listed here.

Navigation.ascx.jsl
 packageFourthCoffee; importSystem.*; importSystem.Data.*; importSystem.Drawing.*; importSystem.Web.*; importSystem.Web.UI.WebControls.*; importSystem.Web.UI.HtmlControls.*; /** *SummarydescriptionforNavigation. */ publicabstractclassNavigationextendsSystem.Web.UI.UserControl { protectedSystem.Web.UI.WebControls.LabelLabel1; protectedSystem.Web.UI.WebControls.ButtonHomeButton; protectedSystem.Web.UI.WebControls.LabelLabel2; protectedSystem.Web.UI.WebControls.ButtonHelpButton; privateSystem.StringhomeUrl= "default.htm"; privateSystem.StringhelpUrl=null; /**@property*/ publicvoidset_HelpUrl(System.Stringurl) { if(url!=null&&url.get_Length()!=0) { helpUrl=url; HelpButton.set_Enabled(true); } } /**@property*/ publicSystem.Stringget_HelpUrl() { returnhelpUrl; } privatevoidPage_Load(System.Objectsender,System.EventArgse) { //Putusercodetoinitializethepagehere if(helpUrl==null) { HelpButton.set_Enabled(false); } } #regionWebFormDesignergeneratedcode protectedvoidOnInit(System.EventArgse) { // //CODEGEN:ThiscallisrequiredbytheASP.NETWebFormDesigner. // InitializeComponent(); super.OnInit(e); } /** *RequiredmethodforDesignersupport-donotmodify *thecontentsofthismethodwiththecodeeditor. */ privatevoidInitializeComponent() { this.HomeButton.add_Click(newSystem.EventHandler(this.HomeButton_Click)); this.HelpButton.add_Click(newSystem.EventHandler(this.HelpButton_Click)); this.add_Load(newSystem.EventHandler(this.Page_Load)); } #endregion privatevoidHomeButton_Click(System.Objectsender,System.EventArgse) { GoToPage(homeUrl); } privatevoidHelpButton_Click(System.Objectsender,System.EventArgse) { GoToPage(helpUrl); } privatevoidGoToPage(System.Stringpage) { if(page.EndsWith(".aspx")) { get_Server().Transfer(page); } else { get_Response().Redirect(page); } } } 
Using a User Control

Once you've defined a user control, you can add it to other pages by registering it in the ASPX file of each host page. The following registration directive, used in the sample file Login.aspx, indicates that the tag Navigation , prefixed by FourthCoffee , refers to the class contained in the user control sample file Navigation.ascx:

 <%@RegisterTagPrefix="FourthCoffee" TagName="Navigation" src="Navigation.ascx" %> 

Within the host page, you can use the registered tag to indicate where the control should be positioned. The control declaration itself must be placed within the form for the page (<form runat ="Server"> ). Because the user control does not automatically work with grid layouts, if you're using a grid layout and you want to position the control in a precise location, you can place the control in a Panel Web control and then place the Panel within the form:

 <asp:Panelid="Panel1" style="Z-INDEX:105;LEFT:21px;POSITION:absolute; TOP:271px" runat="server" Height="81px" Width="572px"> <FourthCoffee:Navigationid="navBar" runat="server"> </FourthCoffee:Navigation> </asp:Panel> 

The user control will be displayed within the host page, just like any other Web control. You can see this in Figure 16-14, which shows the Login.aspx page with the Navigation user control visible at the bottom. (It contains the Home and Help buttons together with the logo "Welcome to Fourth Coffee, Your handy cake supplier.")

Figure 16-14. An ASP.NET User Control can be used to group common controls in a single entity.

If your user control contains custom functionality, such as the HelpUrl property discussed previously, you'll want to access this programmatically. Within the host page, you can add code to find the user control within the Panel and set its property, as shown here:

 NavigationnavBar=null; IEnumeratorenumerator=Panel1.get_Controls().GetEnumerator(); while(enumerator.MoveNext()) { Controlctrl=(Control)enumerator.get_Current(); System.StringcontrolName=ctrl.GetType().get_Name(); System.StringcontrolName1=ctrl.GetType().get_FullName(); if(controlName.CompareTo("Navigation_ascx")==0) { navBar=(Navigation)ctrl; break; } } navBar.set_HelpURL("LoginHelpPage.htm"); 

You can find this code in the PageLoad method of the sample file Login.aspx. This sample file also contains session and cookie manipulation (covered later).

Binding to Data

As mentioned in the previous section, some of the Web controls are intended for use with ADO.NET data sources. These controls are associated with, or bound to , a data source so that when they're rendered they reflect the contents of that data source. Again, an exhaustive examination of data binding to Web controls is outside the scope of this chapter, but we'll give you an idea of what you can do and how to perform simple data binding in J#. You can do many more things, such as paging through large amounts of data and handling events generated by user interaction.

Binding XML

As an example of data binding, consider the use of a DataGrid as a means of displaying the contents of the Fourth Coffee cake catalog. Given the catalog data in an ADO.NET DataSet , the DataGrid can generate a representation of one of the tables in the DataSet . The DataGrid will infer column names based on the columns in the underlying table. By default, the DataGrid will display the first table in the DataSet . To display another table, you can set the DataMember property of the DataGrid to that table.

A simple way to create an ADO.NET DataSet to which you can bind a DataGrid is to base one on an XML document. Recall from Chapter 5 and Chapter 7 that an ADO.NET DataSet leads a secret double life as an XmlDataDocument . Use this fact by loading XML into the DataSet and then binding the DataSet to a control. Consider the XML document in the CakeCatalog.xml sample file, shown below. This document maps to a DataSet comprising three tables, whose names are inferred from the schema of the XML document:

  • CakeType , which maps to the <CakeType> element and contains the message, style, filling, shape, and description

  • Option, which maps to the <Option> element and contains a list of the possible sizes

  • Sizes , which maps to the <Sizes> element and is basically a key mapping table between the CakeType table and the Option table.

    CakeCatalog.xml
     <?xmlversion="1.0" encoding="utf-8" ?> <CakeCatalog> <CakeTypestyle="Celebration" filling="sponge" shape="round"> <Message>HappyBirthday</Message> <Description>Oneofourmostpopularcakes</Description> <Sizes> <Optionvalue="10inch" /> <Optionvalue="12inch" /> <Optionvalue="14inch" /> </Sizes> </CakeType> <CakeTypestyle="Wedding" filling="sponge" shape="square"> <Message/> <Description>A3-tiercreationtograceanyceremony</Description> </CakeType> <CakeTypestyle="Wedding" filling="fruit" shape="round"> <Message/> <Description>Aheaviercakeforhungrierguests</Description> </CakeType> <CakeTypestyle="Christmas" filling="fruit" shape="square"> <Message>Season'sGreetings</Message> <Description>Spicyfruitcakeforcoldevenings</Description> <Sizes> <Optionvalue="12inch" /> <Optionvalue="14inch" /> </Sizes> </CakeType> </CakeCatalog> 

To display this data, we created a simple Web Form called ShowXmlCatalog.aspx in the FourthCoffee project, which contains two DataGrid controls. In the code-behind file ShowXmlCatalog.aspx.jsl, the XML document in the file CakeCatalog.xml is loaded into the DataSet called xmlCatalog . The application uses the MapPath method of the HttpServerUtils object to ensure that the filename is correct relative to the current virtual directory. The DataSet is then assigned to the DataSource property of two DataGrid controls. One DataGrid will display the cake type information, and the other will display the size options. To do this, the DataMember property is set to the appropriate inferred table name ( CakeType and Option , respectively) and then the DataBind method is called. You will find the complete ShowXmlCatalog.aspx.jsl file in the FourthCoffee sample project.

The result of this data binding is shown in Figure 16-15.

Figure 16-15. Simple data binding using a DataGrid and an XML document

All of this binding code is performed in the Page_Load method. If you've cached the DataSet when the page is first loaded or if you're binding different data based on user feedback, you might want to check the IsPostBack property before performing data loading or binding.

Binding SQL Data

As you've seen, the DataSet representation of the XmlDataDocument allows an XML document to be bound to a control. Hence, any binding you saw in the previous section can be performed equally well with a DataSet populated with data obtained from any other form of underlying data source.

You can also use a DataReader as a data source for the data binding of Web controls. This can be more efficient than using a DataSet when the data in question is read-only and cannot be cached and therefore must be retrieved every time.

I l @ ve RuBoard


Microsoft Visual J# .NET (Core Reference)
Microsoft Visual J# .NET (Core Reference) (Pro-Developer)
ISBN: 0735615500
EAN: 2147483647
Year: 2002
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net