<asp:Button> Control

Server scripts are activated by events surrounding the Web page. The usual way to call these scripts is through event handlers attached to controls. The <asp:Button> control is the most common method to activate scripts. It displays a clickable button that calls a subprogram or performs submission of the form on which it is contained. The general format for this control is shown below.

<asp:Button id="id" Runat="Server"
  CommandArgument="argument"
  CommandName="command"
  PostBackUrl="url"
  Text="string"
  
  property="value"...
  
    OnClick="subprogram"
    OnCommand="subprogram"
/>
Figure 5-1. General format for <asp:Button> control.

An id is not required unless the button's identity is referenced by the called subprogram. The Text attribute provides the label for the button. The OnClick event handler identifies a subprogram to run when the button is clicked. The OnCommand, CommandName, and CommandArgument properties call a subprogram to pass along data or control information needed to perform processing.

Clicking a button performs a post-back operation. The page is reloaded, the Page_Load subprogram, if coded, is run, followed by the subprogram named in the OnClick event handler. Normally, post-back is to the same page. However, a different page, named in the PostBackUrl property can be called.

Calling a Subprogram

Normally a button's purpose is to call a subprogram by supplying the subprogram's name in an OnClick event handler coded in the button. The following button operates in this fashion. The called subprogram simply assigns a text string to an accompanying Label control.




Figure 5-2. Using a button to call a subprogram.
<SCRIPT Runat="Server">

Sub Button_Click (Src As Object, Args As EventArgs)
  Message.Text = "The Button_Click subprogram was run."
End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button Text="Call Button_Click" OnClick="Button_Click" Runat="Server"/>
<asp:Label id="Message" Runat="Server"/>

</form>
Listing 5-1. Coding a Button control.

Recall that a subprogram called by a button has the special signature (source As Object, arguments As EventArgs). Programmer-supplied names are provided for the source and arguments variables in the argument list. These tutorials use the names (Src As Object, Args As EventArgs); other identifiers can be used. It is common to see the names "sender" and "e" used for the two arguments: (sender As Object, e As EventArgs).

The source argument identifies the button that is clicked to call the subprogram; arguments refer to any supporting data items passed to the subprogram. In the case of a normal subprogram call, neither source nor arguments comes into play. If, however, the subprogram needs to refer to the clicked button, say to style it as visual indication that it was clicked, then the source argument is used. In the following example, a button has its colors and label changed to indicate it has been clicked.




Figure 5-3. Scripting a button style.
<%@ Import Namespace="System.Drawing" %>

<SCRIPT Runat="Server">

Sub Button_Click (Src As Object, Args As EventArgs)
  Src.BackColor = Color.FromName("#FF0000")
  Src.ForeColor = Color.FromName("#FFFFFF")
  Src.Font.Size = FontUnit.Parse("11pt")
  Src.Text = "I've been clicked!"
  Message.Text = "The button '" & Src.id & "' was clicked."
End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button id="MyButton" Text="Click Me" Runat="Server"
  OnClick="Button_Click"/>
<asp:Label id="Message" Runat="Server"/>

</form>
Listing 5-2. Code to script button styling.

The source argument (Src in this example) is the reference used to set server style properties of the button along with its Text property. The id property of the button (Src.id) is used in a message produced for the output Label. Note that it is not necessary to assign the button an id. The Src reference identifies the button whether explicitly identified or not.

Scripting Command Buttons

A Button can be configured as a command button to pass control information to a subprogram so that a single script can service multiple buttons and take appropriate action for the particular button that is clicked. Buttons used in this way are coded with OnCommand (rather than OnClick) event handlers. They include CommandName and CommandArgument properties to supply processing control information to the subprogram.

A subprogram called with OnCommand has a different signature from one called with OnClick. Rather than EventArgs, the argument list uses CommandEventArgs. It is through this argument that the passed CommandName and CommandArgument values are received.

The following example demonstates a subprogram called by a command button. The subprogram reports values associated with the arguments passed by the button.


 

Figure 5-4. Using a command button to call a subprogram.
<SCRIPT Runat="Server">

Sub Report_Arguments (Src As Object, Args As CommandEventArgs)

  PassedValues.Text  = "<b>Src.id</b> = " & Src.id & "<br/>"
  PassedValues.Text &= "<b>Args.CommandName</b>= " & _
                        Args.CommandName & "<br/>"
  PassedValues.Text &= "<b>Args.CommandArgument</b>= " & _
                        Args.CommandArgument & "<br/>"

End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button id="MyButton" Runat="Server"
  Text="Report Arguments"
  OnCommand="Report_Arguments"
  CommandName="Do Something"
  CommandArgument="With This Value"/>

<p><asp:Label id="PassedValues" Runat="Server"/></p>

</form>
Listing 5-3. Code to script a command button.

When the button is clicked, subprogram Report_Arguments is called. Because the subprogram is called through an OnCommand event handler, the button also sends its CommandName and, if present, CommandArgument values to the subprogram.

The subprogram identifies the clicked button through its source argument. The subprogram also receives through its arguments list any CommandName and CommandArgument values that are passed. In this example, Args.CommandName and Args.CommandArgument give these values. Both are programmer-supplied values to pass processing control information to the subprogram; they have no intrinsic values that are meaningful to the subprogram.

The main reason for using an OnCommand event handler is to be able to differentiate between multiple buttons calling the same subprogram. This capability is illustrated by the following two buttons which call the same subprogram. Here, different buttons produce different reports on their passed arguments.


Figure 5-5. Using command buttons to call a subprogram.
<SCRIPT Runat="Server">

Sub Report_Arguments (Src As Object, Args As CommandEventArgs)

  PassedValues.Text  = "<b>Src.id</b> = " & Src.id & "<br/>"
  PassedValues.Text &= "<b>Args.CommandName</b>= " & _
                        Args.CommandName & "<br/>"
  PassedValues.Text &= "<b>Args.CommandArgument</b>= " & _
                        Args.CommandArgument & "<br/>"
	
End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button id="FirstButton" Runat="Server"
  Text="Report Arguments" 
  OnCommand="Report_Arguments" 
  CommandName="Do This"
  CommandArgument="With This Value"/>

<asp:Button id="SecondButton" Runat="Server"
  Text="Report Arguments" 
  OnCommand="Report_Arguments" 
  CommandName="Do That"
  CommandArgument="With That Value"/>

<p><asp:Label id="PassedValues" Runat="Server"/></p>

</form>
Listing 5-4. Code to script a pair of command buttons.

As you can see, there are three different ways to distinguish buttons from one another. They can be differentiated by their id values; they can be differentiated by their CommandName values; they can be differentiated by their CommandArgument values. A subprogram can use any combination of these passed values to differentiate processing requests.

Coding Choices

It is often not necessary to supply all three arguments to determine which processing option is carried out by a subprogram. If, for instance, it is only a matter of choosing either of two processing tasks requested by two different buttons, then the buttons' ids are sufficient information for the subprogram to make the choice. It is not necessary to supply CommandName or CommandArgument values. The following subprogram is coded to distinguish between two buttons in order to take two processing routes.

<SCRIPT Runat="Server">

Sub Do_Processing (Src As Object, Args As CommandEventArgs)
  
  If Src.id = "FirstButton" Then
    ...do this processing
  End If

  If Src.id = "SecondButton" Then
    ...do this processing
  End If

End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button id="FirstButton" OnCommand="Do_Processing" Runat="Server"/>
<asp:Button id="SecondButton" OnCommand="Do_Processing" Runat="Server"/>

</form>
Listing 5-5. Referencing a source object of a subprogram call.

An alternative to the above coding is to supply CommandNames instead of id values to distinguish processing choices. One reason for doing this would be to make more explicit the processing choices represented by the buttons.

<SCRIPT Runat="Server">

Sub Do_Processing (Src As Object, Args As CommandEventArgs)

  If Args.CommandName = "Process1" Then
    ...do this processing
  End If

  If Args.CommandName = "Process2" Then
    ...do this processing
  End If
	
End Sub

</SCRIPT>

<form Runat="Server">
<asp:Button OnCommand="Do_Processing" CommandName="Process1" Runat="Server"/>
<asp:Button OnCommand="Do_Processing" CommandName="Process2" Runat="Server"/>

</form>
Listing 5-6. Using a CommandName to determine processing choices.

A second and more common reason for using CommandNames is to pass along data values that are involved in the processing. In the following example, two buttons supply the same subprogram with different data values to be involved in the same processing.

<SCRIPT Runat="Server">

Sub Do_Processing (Src As Object, Args As CommandEventArgs)

  ...do processing with Args.CommandName '-- with "Data1" or "Data2"

End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button OnCommand="Do_Processing" CommandName="Data1" Runat="Server"/>
<asp:Button OnCommand="Do_Processing" CommandName="Data2" Runat="Server"/>

</form>
Listing 5-7. Using a CommandName to supply different data values.

If a subprogram offers additional processing choices, then both CommandName and CommandArgument properties might be needed to isolate these choices. In the following example, four buttons call the same subprogram requesting different sorting actions on different data fields.

<SCRIPT Runat="Server">

Sub Do_Sorting (Src As Object, Args As CommandEventArgs)

  If Args.CommandName = "Sort1" Then
    If Args.CommandArgument = "SortUp" Then
      ...sort field 1 ascending
    End If
  End If
  If Args.CommandName = "Sort1" Then
    If Args.CommandArgument = "SortDown" Then
      ...sort field 1 descending
    End If
  End If

  If Args.CommandName = "Sort2" Then
    If Args.CommandArgument = "SortUp" Then
      ...sort field 2 ascending
    End If
  End If
  If Args.CommandName = "Sort2" Then
    If Args.CommandArgument = "SortDown" Then
      ...sort field 2 descending
    End If
  End If

End Sub

</SCRIPT>

<form Runat="Server">

<asp:Button Text="Sort 1 Ascending" Runat="Server"
  OnCommand="Do_Sorting"
  CommandName="Sort1"
  CommandArgument="SortUp"/>

<asp:Button Text="Sort 1 Descending" Runat="Server"
  OnCommand="Do_Sorting"
  CommandName="Sort1"
  CommandArgument="SortDown"/>

<asp:Button Text="Sort 2 Ascending" Runat="Server"
  OnCommand="Do_Sorting"
  CommandName="Sort2"
  CommandArgument="SortUp"/>

<asp:Button Text="Sort 2 Descending" Runat="Server"
  OnCommand="Do_Sorting"
  CommandName="Sort2"
  CommandArgument="SortDown"/>

</form>
Listing 5-8. Referencing a passed CommandArgument in a subprogram call.

For most processing requirements, it is usually not necessary to include these additional levels of button differentiation. Differering id and/or CommandName arguments are usually sufficient. If a subprogram requires an additional CommandArgument to differentiate choices, then you might consider whether the single subprogram is trying to do too much.

Using Buttons for Database Display

The following example is an illustration of the use of command buttons. All buttons call the same subprogram to select display of book types from the BooksDB.mdb database. The subprogram issues differently composed SQL statements to select different recordsets for display in a GridView. The different SQL statements depend on the different CommandName arguments passed by the buttons. This application uses an AccessDataSource to connect to the database and a basic GridView to display results.

View Book Types


BookIDBookTitleBookPrice
DB111Oracle Database$69.99
DB222Databases in Depth$29.95
DB333Database Processing$136.65
DB444Access Database Design$34.95
DB555SQL Server 2005$29.99

Figure 5-6. Using command buttons to issue SQL statements for book displays.

Script and control coding for this output is shown below. Notice that the buttons have CommandName values indicating the BookType field from the database to be used for selecting subsets of records.

<SCRIPT Runat="Server">

Sub Show_Books (Src As Object, Args As CommandEventArgs)
  
  Dim SQLString As String
  SQLString = "SELECT BookID, BookTitle, BookPrice FROM Books " & _
              "WHERE BookType = '" & Args.CommandName & "'"
  BookSource.SelectCommand = SQLString

End Sub

</SCRIPT>

<form Runat="Server">

<h3>View Book Types</h3>

<asp:Button Runat="Server"
  Text="Database"
  OnCommand="Show_Books"
  CommandName="Database"
  Width="80"/>

<asp:Button Runat="Server"
  Text="Graphics"
  OnCommand="Show_Books"
  CommandName="Graphics"
  Width="80"/>

<asp:Button Runat="Server"
  Text="Hardware"
  OnCommand="Show_Books"
  CommandName="Hardware"
  Width="80"/><br/>

<asp:Button Runat="Server"
  Text="Software"
  OnCommand="Show_Books"
  CommandName="Software"
  Width="80"/>

<asp:Button Runat="Server"
  Text="Systems"
  OnCommand="Show_Books"
  CommandName="Systems"
  Width="80"/>

<asp:Button Runat="Server"
  Text="Web"
  OnCommand="Show_Books"
  CommandName="Web"
  Width="80"/>

<asp:AccessDataSource id="BookSource" Runat="Server"
  DataFile="../Databases/BooksDB.mdb"
  SelectCommand="SELECT BookID, BookTitle, BookPrice FROM Books
                 WHERE BookType = 'Database'"/>

<p><asp:GridView DataSourceID="BookSource" Runat="Server"/></p>

</form>
Listing 5-9. Code to issue SQL command depending on CommandName of clicked button.

The AccessDataSource is originally coded with a SelectCommand to retrieve a subset of records for initial GridView display. Subsequently, the GridView displays other subsets of records corresponding with button clicks.

BookType values are received by subprogram Show_Books through the CommandName property of its CommandEventArgs argument (Args.CommandName). These command names, which are also the BookType values appearing in the database, are concatenated within a SELECT statement to select records with these BookType values. For instance, if the first button is clicked (CommandName="Database"), the following SQLString value is produced.

SQLString = "SELECT BookID, BookTitle, BookPrice FROM Books " & _
            "WHERE BookType = '" & Args.CommandName & "'"

-- becomes --

SELECT BookID, BookTitle, BookPrice FROM Books WHERE BookType = 'Database'
Listing 5-10. SQL statement produced by clicking a button.

When this SQLString variable is script-assigned to the AccessDataSource's SelectCommand property, the data source is immediately bound to the GridView to display these selected books.

Posting to a Different Page

Normally, a button click posts back to the same page on which the button appears. This is the default behavior of the button's OnClick event handler. You can, instead, post to a different page and still be able to access controls on the original page. Posting to a different page takes place through the button's PostBackUrl property. This property gives the URL of the page to which to post.

In the following example, a page contains two controls, a Button and a Label. The button includes the PostBackUrl property to post to page PostPage.aspx located in the same directory. When PostPage.aspx opens, it accesses the button id and label Text from the previous (posting) page.

Using PostBackUrl

Button:

Label:  Text value to post

Figure 5-7. Posting to a different page.

Code for the posting page is shown below with a Button containing the PostBackUrl property and a Label containing a text string for posting to PostPage.aspx.

<h4>Using PostBackUrl</h4>

Button: <asp:Button id="PostingButton" Text="PostPage.aspx" Runat="Server"
         PostBackUrl="PostPage.aspx"/><br/><br/>

Label:  <asp:Label id="PostedValue" Text="Text value to post" Runat="Server"
         BorderStyle="Ridge" Style="padding-left:10px; padding-right:10px"/>
Listing 5-11. Code to post to a different page.

The PostBackUrl page, PostPage.aspx, includes a script to locate the Button and Label controls on the posting page and to report their id and Text values, respectively.

<SCRIPT Runat="Server">

Sub Page_Load
  
  Dim FoundButton As Button
  FoundButton = PreviousPage.FindControl("PostingButton")
  PostButton.Text = FoundButton.id
  
  Dim FoundLabel As Label
  FoundLabel = PreviousPage.FindControl("PostedValue")
  PostValue.Text = FoundLabel.Text

End Sub

</SCRIPT>

<form Runat="Server">

<h3>This is PostPage.aspx</h3>

<p>The button with the id 
"<asp:Label id="PostButton" Font-Bold="True" Runat="Server"/>"
posted the text value 
"<asp:Label id="PostValue" Font-Bold="True" Runat="Server"/>"
from the previous page.

<p><a href="PostingPage.aspx">Return</a></p>

</form>
Listing 5-12. Code to retrieve and displays values from posting page.

The FindControl() Method

The page to which a posting is made through the PostBackUrl property of a button does not have direct access to controls on the posting page. That is, a script on PostPage.aspx cannot directly reference the Button or the Label on the posting page. It cannot, as can be done on a page posted back to itself, use PostingButton.id or PostedValue.Text to directly retrieve the id and Text properties of these controls on the posting page.

The technique that must be used involves first finding the controls of interest on the previous page and then referencing properties of these found controls. The posting page is identified through the PreviousPage property; controls on this page are located with its FindControl() method. The FindControl() method of PreviousPage has the general formats shown in Figure 5-8.

Dim FoundControl As ControlType
FoundControl = PreviousPage.FindControl("id")

or

Dim FoundControl As ControlType = PreviousPage.FindControl("id")
Figure 5-8. General format to locate a control on a posting page.

First, an object of the type to be located is declared. When locating a Button, for instance, the object is declared as type Button; when locating a Label, the object is declared as type Label. Any ASP.NET control type can be declared to match the control type to be located.

Second, this declared object is assigned the control of interest from the PreviousPage using the FindControl("id") method to identify the control through its id. Once "found" and assigned to the locally declared object, properties of a control appearing on the posting page can be referenced through this local object. This technique is used in the Page_Load subprogram on the PostPage.aspx page.

Sub Page_Load
  
  Dim FoundButton As Button
  FoundButton = PreviousPage.FindControl("PostingButton")
  PostButton.Text = FoundButton.id
  
  Dim FoundLabel As Label
  FoundLabel = PreviousPage.FindControl("PostedValue")
  PostValue.Text = FoundLabel.Text

End Sub
Listing 5-13. Script to locate and report control properties from posting page.

Object reference FoundButton (any programmer-supplied name can be used) is declared as a Button object. It is then assigned the Button with id="PostingButton" located on the PreviousPage (posting page). Likewise for the Label. Object reference FoundLabel is declared as a Label object. The Label with id="PostedValue" on the PreviousPage is assigned to this script object. Thereafter, properties associated with these controls appearing on the posting page are accessible through their surrogate references on the current page. In this example, FoundButton.id accesses the id property of the Button on the posting page; FoundLabel.Text accesses the Text property of the Label on the posting page. These two values are displayed in Labels appearing on the posted page.

You need to become familiar with the FindControl() method. It has many uses under ASP.NET besides locating controls on pages which issue PostBackUrls. It is routinely used to locate controls embedded inside other controls on the same page.