This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


Beyond the Browser
beyond@microsoft.com
Ken Spencer

The ASP PageObject

V
isual InterDev™ 6.0 includes a number of design-time controls that can be used as building blocks in your applications. The PageObject design-time control will make creating your Web applications faster and easier. The PageObject control exposes events, methods, and properties of a page, so you can treat the page as an object.
      PageObject is useful for a wide range of tasks from setting up properties for a page to initializing a design-time control's properties at runtime. Let's see how to use the PageObject control in several typical Web app tasks.

Using PageObject with Design-Time Controls
      It will often be necessary to initialize a design-time control in some way when a user first visits a page. Let's create a simple page that uses a Listbox design-time control to allow a user to select a record from a recordset.
      To start the sample, add a data connection to any ODBC database. (I used the Pubs database shipped with SQL Server™ for all samples in this column.) Next, create a new ASP file, then drag a Recordset design-time control from the Toolbox onto the page in the body section, just after the <BODY> tag. Answer Yes when you're asked if you want to enable the scripting object model.
      Next, open the properties for the Recordset design-time control. Name the recordset, then click the "SQL statement" radio button. Enter a SQL statement to extract all the records from a table. I used the following statement for this sample:

 select * from authors
Now close the recordset property page.
      Drag a Listbox design-time control from the Toolbox onto the page after the recordset. Open the properties for the listbox and click the Lookup tab. Select the recordset name you chose from the "Row source" list. Select the field you want to display in the list for both the "Bound column" and "List field" entries. The list field is the one the user will see in the list when the page is rendered in the browser. The bound column is the value that will be returned when the user selects an item in the list. This lets you display one value (such as a name) and return a different value (such as an employee number). The properties for my sample page are shown in Figure 1.
Figure 1: Sample Listbox Properties
Figure: Sample Listbox Properties

      Now let's add some code for the onchange event. First, display the Script Outline by clicking the tab under the Toolbox or by pressing Ctrl+Alt+S. You can also display the Script Outline from the View menu or with the shortcut icon on the standard toolbar. Expand the Server Objects & Events folder, then expand Listbox1. Double-click the onchange event to insert an event shell in the page, then add this line of code:
 Response.Write "Listbox output: " & listbox1.getValue()
This line will output the value from the Bound column in the listbox using Reponse.write.
      The completed page is shown in the source editor in Figure 2. Now, let's view the page in the browser (as shown in Figure 3). This page looks normal, right? But when you try to select the first entry in the list when the page opens, nothing happens. Selecting any other entry in the list, then selecting the first entry again makes both work. What's going on?
Figure 3: PageMe
Figure 3: PageMe

      When the page first displays, the first entry in the recordset is shown in the list. When the user selects this entry, there is no change in the value of the list, so the onchange event does not fire. Selecting any other list entry works because it is not the same as the current contents.
      So how do you fix this? One way is to add a blank entry as the first item in the list. You can do this by using this code:
 Listbox1.addItem "","",0
The value 0 in the third parameter specifies that this should be the first item in the list. Now, when the page displays you will see a blank entry as the first item in the list. You can select any entry in the list with no problem, but what happens to the entries in the list? Each time you select an item in the list, another blank entry is added to it. This is not what you want.
      Now what? The PageObject control has a set of useful server events and properties. These server events are available when PageObject is using the server design-time control scripting platform. When you add the PageObject design-time control to a page, the thisPage Object shows up in the Script Outline. One of the events provided by PageObject is onenter, which fires each time a page is executed. It fires whether a user explicitly navigates to the page or the page executes as a result of a user event such as a user selecting an item from a list. Onenter is a handy place to put code that you want to execute each time a page is executed. In this example, I'll use it to perform some action on the listbox each time the page executes.
      PageObject also provides the firstEntered property. This property returns true when a user navigates to a page for the first time, then false when the page is executed for that user again. Coupling this property with the onenter event allows you to place code in a page that executes either on the first access or subsequent accesses by a user. Let's add this code to the page and see what happens.
      First, drag the PageObject design-time control from the Toolbox and drop it on the page just after the listbox. Next, display the Script Outline again. Expand the Server Objects & Events, then expand thisPage. Double-click the onenter event and the event code will be added to your page.
      Next, move the line you entered before inside this event code and add an if statement around it. The resulting code should look like this:
 Sub thisPage_onenter()
     if thispage.firstEntered then
         Listbox1.addItem "","",0
     end if
 End Sub
This code will add a blank entry to the list the first time the user navigates to the page. However, it won't add the entry when the page executes as a result of the user selecting an entry from the list.
      There is one other server event you can use with PageObject: the onexit event executes when the page completes processing. This allows you to group statements that should execute when the page processing is complete.
      If you have told Visual InterDev to implement the scripting platform as Client (under Microsoft Internet Explorer 4.0), the onbeforeserver event fires before any code is sent to the server. I will discuss client design-time control implementations in more detail in a future column.

Using PageObject Properties and Methods
      PageObject offers other features that allow you to perform some interesting actions with your application. When you drop a PageObject control onto a page, that page becomes an object in your application. You can use PageObject to expose the methods and properties of any page it is used on. This will let you access those methods and properties from any other page in the application. The result is that each page in your application can now appear as an object to your application. This makes building a framework of reusable methods and properties simpler.
      You must explicitly add the properties and methods for a page to the PageObject control by using its property page. Once you have done this, other pages can access the object model of this page. All that you have to do is create a reference to the page that contains them.
      Let's look at an example of these features. First, let's create a property in the PageObject control. Open the properties of the PageObject in your sample page, and click the Properties tab. In the name column, enter a name for the property (I used PhoneNumber and LastName for my two properties). Next, select the Lifetime for the property. This controls the scope of the property and its implementation method. You can choose one of three Lifetime settings: Page makes a property available to scripts anywhere on the page until you navigate to another page; Session makes the property available to any page a user navigates to in this application; Application makes the property available to any page within the application.
      The Lifetime setting also controls the implementation of the property. When you set a property to Page scope, the value is stored in the page and is only available during the lifetime of that page. If you set a property's Lifetime to Session, ASP Session variables are used to store values. A Lifetime setting of Application uses ASP Application variables to store values.
      The Client and Server columns define how script code can access a property. The default setting is for read access to client scripts and read/write access to server scripts. This allows you to control how the properties can be used in your application. Figure 4 shows the settings that I used in this sample page.

Figure 4: PageObject Properties
Figure 4: PageObject Properties

      Now, what can you do with the properties? When you create a property for the PageObject, two methods are created for the PageObject and the property. Getxxx retrieves the value of propertyxxx and setxxx sets the value of propertyxxx. Whenever you need to access a property, you must use these methods to set data to or retrieve data from the property. To illustrate this, let's look at how to use these two methods.
Figure  5: Using the Get and Set Methods
Figure 5: Using the Get and Set Methods

      I added two design-time control textboxes and a design-time control button to the sample page. The results are shown in the browser in Figure 5. To add these functions to your page, add a two-row, two-column HTML table to hold the textboxes. Then drop a Textbox design-time control into the second column in each row. Next, drag a Button design-time control onto the page after the end of the table. I named the button cmdGetValue.
      Open the page in source view. Modify the Listbox1_onchange code used earlier to look like this:
 PageMe.setLastName(listbox1.getText())
 PageMe.setPhoneNumber(listbox1.getValue())
 txtLastName.value = ""
 txtPhoneNumber.value = ""
The first line takes the value shown in the listbox and places it in the LastName property. The second line takes the value in the Bound column of the current record in the listbox and places it in the PhoneNumber property.
      Notice the syntax used for both lines. The setxxx and getxxx members are methods, not properties. You must pass the value to the setxxx method as a parameter; don't assign it like a variable. For instance, if you use this syntax
 PageMe.setPhoneNumber = listbox1.getValue()
the code will not work. The last two lines for the onchange event clear the two textboxes. This makes sure the previous values are cleared when you select another item from the list.
      Next, open the Script Outline, expand Server Objects & Events, then expand the design-time control button. Double-click the button's onclick event to add the event to your page. Now, add this code to the onclick event:
 txtLastName.value = PageMe.getLastName()
 txtPhoneNumber.value = PageMe.getPhoneNumber()
These two lines retrieve the value from the two PageObject properties and place them in the textboxes. Now you can click the button to retrieve the values stored when the user selected them from the list. This makes it extremely easy to create properties and use them throughout your application.
      How does this relate to exposing properties across pages? Using this example, let's access these properties from another page. First, create a new ASP file. Copy the table containing the textboxes and the design-time control button from the previous example and paste them into the new page. Then add a PageObject control to the page. At this point, the new page should look exactly like the first page, except for the listbox.
      Open the properties for the PageObject design-time control, then click the References tab. Click the ellipsis and find the PageMe.asp file from the last example. Select this page and click OK. The property page should now look like the one in Figure 6. That's all you need to do to create the reference to the other page.
Figure 6: PageMe Properties
Figure 6: PageMe Properties

      Next, open the Script Outline for the new page, expand Server Objects & Events, then expand the entry for the design-time control button. Double-click the button's onclick event to add the event to your page. Add this code to the onclick event:
 txtLastName.value = PageMe.getLastName()
 txtPhoneNumber.value = PageMe.getPhoneNumber()
This looks like the same code from PageMe.asp, doesn't it? It is. You reference properties across pages using the same syntax as you do to reference the property in the same page. The syntax you use with a getxxx method is as important as it is with the setxxx method. If you enter the getxxx method without the closing parens, the variable will receive strange results.

Conclusion
      Using the PageObject makes it easier to create properties for your page and to use them throughout the application. It also reduces the number of errors you will interject into your application when using these properties.
      You can define methods in the same manner as properties, although you must define the methods in a page's code first. The PageObject design-time control provides access to methods across pages on the server and from client script running in the browser. In my next column, I will show you how to use PageObject methods with properties and other ASP and Visual InterDev features.


From the December 1998 issue of Microsoft Interactive Developer.