Tải bản đầy đủ (.pdf) (90 trang)

Beginning ASP.NET 1.1 with Visual C# .NET 2003 phần 5 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.18 MB, 90 trang )


Figure 10-10
3. Drag a DataList control into the first cell of the table from the Web Controls panel on the left, as
shown in Figure 10-11:
Figure 10-11
4. Let's do some work on the code in the page. First, switch to HTML view and enter the following
code:
<asp:DataList id="TeamList" runat="server">
<ItemTemplate>
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "TeamName") %>'
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "TeamID") %>'
id="TeamNameLink" style="color:darkred" runat="server" />
<br />
<asp:Label text='<%# DataBinder.Eval(Container.DataItem, "Notes") %>'
id="teamnotes" runat="server" />
</ItemTemplate>
<SeparatorTemplate>
<br />
<hr color="#b0c4de" width="200px"/>
</SeparatorTemplate>
</asp:DataList>
We've entered some data binding expressions in here, but not yet created a data source for this
control. Next, you'll need to grab the name of each of the teams from the database, and create an
ID for each team. This ID will come in handy when you need to get more information about
333
ASP.NET Server Controls
each of the teams. In addition, you'll need to grab data from the Notes field that describes each
of the teams. Both of these tasks will be carried out next.
5. The first step is to add some data source information to the page. We're going to use the neat
data wizard feature of Web Matrix to generate some database access code. In


Code view, drag a
SELECT Data Method wizard onto the page from the Code Wizards panel on the left, which shows
up as shown in Figure 10-12:
Figure 10-12
6. Create a new database connection to the WroxUnited database by selecting your preferred
database type, and clicking on the
Create button. If you are using Access, you will be prompted
to enter the path to the database. If you are using MSDE, you will be prompted to select the
WroxUnited database from your database list; see Figures 10-13, 10-14, and 10-15:
Figure 10-13
If you are using Microsoft Access, ensure that a copy of the database is placed into
the
BegASPNET11\WroxUnited\Database folder (you need to create this folder if it
doesn't already exist).
334
Chapter 10
Figure 10-14
Figure 10-15
Now that you have a connection to your database, you can go ahead with the Code Wizard.
7. Click Next, and the Code Wizard is launched. All you need is data from the Teams table, so
select the
Teams table, then select each field from that table, as shown in Figure 10-16:
In this book, the examples use the Access version of the database, but you can
obviously use the SQL Server version. In fact, in Appendix D, a SQL Server
connection has been used instead.
335
ASP.NET Server Controls
Figure 10-16
8. Click Next, and you can test out the query. You should see a screen similar to Figure 10-17:
Figure 10-17

9. In the final screen, save this method as GetTeams(), ensure that the DataReader type is selected,
and then click
Finish, as shown in Figure 10-18:
336
Chapter 10
Figure 10-18
Back in
Code view, you will now see the following:
System.Data.IDataReader GetTeams()
{
string connectionString =
"Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4;" +
"Data Source=C:\\BegASPNET11\\WroxUnited\\Database\\WroxUnited.mdb";
System.Data.IDbConnection dbConnection = new
System.Data.OleDb.OleDbConnection(connectionString);
string queryString = "SELECT [Teams].[TeamID], [Teams].[TeamName], " +
"[Teams].[Notes] FROM [Teams]";
System.Data.IDbCommand dbCommand = new System.Data.OleDb.OleDbCommand();
dbCommand.CommandText = queryString;
dbCommand.Connection = dbConnection;
dbConnection.Open();
System.Data.IDataReader dataReader =
dbCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
return dataReader;
}
Phew – that's a lot of code! These code builders are very useful, and we'll be using these quite
often as we build up the site. We now have a function that returns a DataReader object that we
can use to populate the
DataList control. However, before we continue, we need to change this
code a bit. The database connection string can be stored in a central location in the

web.config
file. Since we'll be doing a fair amount of database work for this application, let's change the
code so that we use this technique.
10. Create a new web.config file for your Wrox United application and in the code that is
generated, add the highlighted line of code.
Due to page width limitations, the highlighted line in the following code snippet has
been wrapped to two lines. You must ensure that the following statement is not
wrapped in your code and is all on one line!
337
ASP.NET Server Controls
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<appSettings>
<add key="ConnectionString"
value="Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4;
Data Source=C:\BegASPNET11\WroxUnited\Database\WroxUnited.mdb"/>
</appSettings>
<system.web>
11. Modify the GetTeams() method as follows to make use of this global connection string:
System.Data.IDataReader GetTeams()
{
string connectionString =
ConfigurationSettings.AppSettings["ConnectionString"];
System.Data.IDbConnection dbConnection = new
System.Data.OleDb.OleDbConnection(connectionString);

12. Add the following code block above the GetTeams() function:
void Page_Load()
{
TeamList.DataSource = GetTeams();

TeamList.DataBind();
}
That's it for this page. Run the page; the output is as shown to Figure 10-19:
Figure 10-19
338
Chapter 10
How It Works
This exercise used many different types of ASP.NET controls to display team information on the page.
Let's look at each of these controls, in turn, starting with the
DataList control.
The
DataList control is a powerful way to display repeated values from a database. It uses templates to
present the data. In this example, we added content for the
ItemTemplate and SeparatorTemplate
elements within the DataList.
The
ItemTemplate section is used to display each row of data retrieved and gives you the option of
adding some layout and styling code:
<asp:DataList id="TeamList" runat="server">
<ItemTemplate>
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "TeamName") %>'
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "TeamID") %>'
id="TeamNameLink" style="color:darkred" runat="server" />
<br />
<asp:Label text='<%# DataBinder.Eval(Container.DataItem, "Notes") %>'
id="teamnotes" runat="server" />
</ItemTemplate>
The SeparatorTemplate is where we added a horizontal line to clearly separate the results:
<SeparatorTemplate>

<br />
<hr color="#b0c4de" width="200px"/>
</SeparatorTemplate>
</asp:DataList>
Inside the ItemTemplate, we used two different controls – an ASP.NET LinkButton control and a
Label control. Let's first look at the LinkButton control:
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "TeamName") %>'
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "TeamID") %>'
id="TeamNameLink" style="color:darkred" runat="server" />
The Text property is set to display the value stored in the TeamName field for each row in the database.
The
CommandArgument property stores the TeamID that represents the currently selected team. This
property will be very useful later on when we use the
LinkButton control to display more information
on the page. Later in this chapter, we'll use it to retrieve a list of players that play for the selected team.
Now, let's look at the
Label control:
<asp:Label text='<%# DataBinder.Eval(Container.DataItem, "Notes") %>'
id="teamnotes" runat="server" />
339
ASP.NET Server Controls
This control is a little simpler than the LinkButton control. The interesting bit is the Text property that
is set to the value stored in the database for the notes for the currently selected team.
Each of these controls will be rendered once for each row in the database. Six teams would result in six
links and six notes. Each result will have the same separator between items.
The code used to access the data stored on the database should be familiar to you from working through
the exercises in Chapters 8 and 9. The Web Matrix data wizard takes a lot of hard work away and
produces neat functions that you can use in your code. However, the Web Matrix wizards don't allow
you to specify a centralized database connection string, so we added a line to the default

web.config
file created for this exercise:
<add key="ConnectionString"
value="Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4;
Data Source=C:\BegASPNET11\WroxUnited\Database\WroxUnited.mdb"/>
Once this was added, the connectionString created by the data access wizard was changed as
follows:
string connectionString =
ConfigurationSettings.AppSettings["ConnectionString"];
This line of code looks up the value stored in the central web.config file and uses that value to connect
to the database.
Linking to the Teams.aspx Page
Before you finish this example completely, flip back to Default.aspx and change the following line of
code as shown:
<asp:HyperLink id="lnkTeams" runat="server" NavigateUrl="Teams.aspx">
Teams
</asp:HyperLink>
Changing the NavigateUrl property means that you can link to the newly created Teams.aspx page
from the main front page.
The DataList control is one of the numerous data controls available to ASP.NET developers. Here's a
quick look at the other controls available to us.
Data Rendering Controls
These controls are extremely feature-rich (they have numerous properties to choose from) and greatly
simplify the work of displaying a variety of data, particularly database-related data. The definition of
340
Chapter 10
data in the context of these controls is very broad. It could include database records, an ArrayList, an
XML data source, or even custom collection of objects containing custom class instances. There are two
important concepts you need to know:


Data binding: This is the term used to describe the process of associating a server control with
information in a data store. Binding data to a server control is a two-step process in ASP.NET –
first assign the server control's
DataSource property to the data you want to bind to and then
call the control's
DataBind() method. Controls can be bound to a variety of data sources,
ranging from tables retrieved from the database to values stored in an object, such as an Array
or a Hashtable.

Templates: These are used to define the various layout elements of a particular control.
Templates describe how data is displayed in the browser.
The following table lists the available data controls:
The DataGrid Control
The DataGrid control provides a wealth of functionality for displaying data in columns and rows and
has many properties that you can use to control the layout of your grid. For example, you could
alternate the colors for the rows of data being displayed. Some useful properties for the
DataGrid
control include:

AllowSorting: Allows you to dynamically sort and re-display the data based on the values in a
selected column. For example, if you have a table in a database containing employees' surnames
and salaries, enabling sorting would allow you to sort the rows in your table according to either
column.
Control Purpose
DataGrid
Creates a multi-column, data-bound grid. This control allows you to define
various types of columns, lay out the contents of the grid, and add specific
functionality (edit button columns, hyperlink columns, and so on).
DataList
Displays items from a data source by using templates and renders them as a

structured table. You can customize the appearance and contents of the
control by manipulating the templates that make up its different components.
Repeater
The Repeater control is very similar to the DataList, except that results are
not rendered in a table. Each row in the data source is rendered in a format
that you specify in the ItemTemplate. Given the lack of structure in the
rendered output, you may find that you use the ItemSeparatorTemplate
more often. Unlike DataList, the Repeater control does not have any built-
in selection or editing support.
341
ASP.NET Server Controls
❑ AllowPaging: Allows you to view subsets of the data called by the DataGrid control on
different pages. The number of items displayed on the page is determined by the
PageSize
property.

AlternatingItemStyle: Sets the style (such as background color) of every other item listed.

ItemStyle: The style of individual items. If no AlternatingItemStyle is defined, all the
items will render with this style.

FooterStyle: The style of the footer (if any) at the end of the list.

HeaderStyle: The style of the header (if any) at the beginning of the list.
To use the
DataGrid control, declare it like the other server controls you've seen (using the
<asp:DataGrid> start and end tags), set the relevant properties, define the columns in your table, and
then apply the relevant template for those columns. Within the template tags, include the information to
which the template must be applied:
<asp:DataGrid id="EventData"

AllowSorting="true"
<Columns>
<asp:TemplateColumn HeaderText="Column1">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "ShortDesc") %>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Column2">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "DetailDesc") %>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
The DataList Control
The DataList control used in the previous example is useful for displaying rows of database
information (which can become columns in
DataGrid tables) in a format that you can control using
templates and styles. Manipulating various template controls changes the way your data is presented. The
DataList control enables you to select and edit the data that is presented. Here is a list of the supported
templates:
342
Chapter 10
You can actually make a DataList render like a DataGrid by arranging data in columns. You can do
this by changing the
RepeatDirection property from Vertical to Horizontal. We recommend
trying this out yourself and taking a look at the source for the rendered page – you'll soon see where you
need to add or remove layout data to customize the appearance of your data.
The Repeater Control
The Repeater control is very similar to the DataList control with one very important distinction: the

data displayed is always read-only. You cannot edit the data being presented. It is particularly useful for
displaying repeating rows of data. Like the
DataGrid and DataList controls, it utilizes templates to
render its various sections. The templates it uses are generally the same as the ones used with the
DataList control, with a similar syntax. The next Try-It-Out illustrates the Repeater control in action.
We've completed the first part of the Teams page, but it would be really useful to see the players on each
team. For that part of the example, we'll work with some more Web controls (including a
Repeater
control) that bind to data.
Try It Out Wrox United – Teams.aspx, Part 2
In this example, we'll make the TeamNames from the previous example "clickable", so that when a team
is selected, the players of that team are listed on the right-hand side of the table.
Templates Purpose
ItemTemplate
This is a required template that provides the content and
layout for items referenced by DataList.
AlternatingItemTemplate
If defined, this template provides the content and layout for
alternating items in the DataList. If it is not defined,
ItemTemplate is used.
EditItemTemplate
If defined, this template provides editing controls, such as
text boxes, for items set to 'edit' in the DataList. If it is not
defined, ItemTemplate is used.
FooterTemplate
If defined, the FooterTemplate provides the content and
layout for the footer section of the DataList. If it is not
defined, the footer section will not be displayed.
HeaderTemplate
If defined, this provides the content and layout for the

header section of the DataList. If it is not defined, the
header section will not be displayed.
SelectedItemTemplate
If defined, this template provides the content and layout for
the currently selected item in the DataList. If it is not
defined, ItemTemplate is used.
SeparatorTemplate
If defined, this provides the content and layout for the
separator between items in the DataList. If it is not defined,
a separator will not be displayed.
343
ASP.NET Server Controls
1. Reopen Teams.aspx, and go straight to Code view. We need to get some more data from the
database. Start by dragging another
SELECT query onto the page and launching the wizard.
2. This time, select PlayerName from the Players table and PositionName from the Positions
table as the two columns to be displayed, as shown in Figure 10-20:
Figure 10-20
3. Before you can exit the wizard, you need to add some WHERE clause data to link the data that
you're gathering. This data comes from two different tables,
Players and Positions. You also
need to ensure that player data is only retrieved for the specific team that you're interested in.
4. Click the WHERE button to start adding a WHERE clause, which selects only those rows where
the
PlayerID column in the PlayerTeam join table matches the PlayerID column in the
Players table as shown in Figure 10-21:
Figure 10-21
344
Chapter 10
5. Repeat this process to join the following sets of tables and columns: the Position column in the

PlayerTeam table to the PositionID column in the Positions table, and the TeamID column
in the
PlayerTeam table to the TeamID column in the Teams table.
6. Finally, set the TeamID column in the PlayerTeam table to be equal to the TeamID parameter, as
shown in Figure 10-22. This will be passed in when the function is called:
Figure 10-22
You should now see the screen shown in Figure 10-23:
Figure 10-23
345
ASP.NET Server Controls
7. Click Next to test the query. When prompted, enter an integer that corresponds to a valid
TeamID, as shown in Figure 10-24 (1 is a safe bet!):
Figure 10-24
You should now see the screen shown in Figure 10-25:
Figure 10-25
8. Save the query as a DataReader called GetPlayersByTeam. You can now exit the wizard. The
following code should have been inserted (we've added a few line breaks in the longer strings
to make it easier to read):
System.Data.IDataReader GetPlayersByTeam(int teamID)
{
string connectionString =
"Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4; " +
"Data Source=C:\\BegASPNET11\\WroxUnited\\Database\\WroxUnited.mdb";
System.Data.IDbConnection dbConnection =
new System.Data.OleDb.OleDbConnection(connectionString);
string queryString =
"SELECT [Players].[PlayerName], [Positions].[PositionName] " +
"FROM [Players], [Positions], [PlayerTeam], [Teams] "+
346
Chapter 10

"WHERE (([PlayerTeam].[PlayerID] = [Players].[PlayerID]) " +
"AND ([PlayerTeam].[Position] = [Positions].[PositionID]) " +
"AND ([PlayerTeam].[TeamID] = [Teams].[TeamID]) " +
"AND ([PlayerTeam].[TeamID] = @TeamID))";
System.Data.IDbCommand dbCommand = new System.Data.OleDb.OleDbCommand();
dbCommand.CommandText = queryString;
dbCommand.Connection = dbConnection;
System.Data.IDataParameter dbParam_teamID =
new System.Data.OleDb.OleDbParameter();
dbParam_teamID.ParameterName = "@TeamID";
dbParam_teamID.Value = teamID;
dbParam_teamID.DbType = System.Data.DbType.Int32;
dbCommand.Parameters.Add(dbParam_teamID);
dbConnection.Open();
System.Data.IDataReader dataReader =
dbCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
return dataReader;
}
Again, the wizard has done a great job of creating complex code with only a few mouse clicks!
You need to make one slight adjustment though, so that the code uses the centralized
connection string added to the
web.config file earlier. Change the following highlighted line of
code to use this central connection string:
System.Data.IDataReader GetPlayersByTeam(int teamID)
{
string connectionString =
ConfigurationSettings.AppSettings["ConnectionString"];
Dim dbConnection As System.Data.IDbConnection = _
New System.Data.OleDb.OleDbConnection(connectionString)
Now, add some controls that can use this code. Switch back to HTML view and add another cell

to the table that contains a
Repeater control:
</td>
<td style="vertical-align:top">
<asp:Repeater id="PlayersList" runat="server">
<ItemTemplate>
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "PlayerName") %>'
style="color:darkred" runat="server"
width="120"/>
&nbsp;&nbsp;
<asp:Label
text='<%# DataBinder.Eval(Container.DataItem, "PositionName") %>'
id="playerposition" runat="server" /><br/>
</ItemTemplate>
<headerTemplate>
Players in: <%= SelectedTeam %>
<hr color="#b0c4de" width="200px">
347
ASP.NET Server Controls
</headerTemplate>
<footerTemplate>
<hr color="#b0c4de" width="200px">
</footerTemplate>
</asp:Repeater>
</td>
</tr>
</table>
With this, you've got a Repeater control and a function to fill it with data. However, a few
things are missing. The

Repeater control should only be filled with data when a team is
selected. We do this in three steps. First, you wire up an event handler so that when the name of
the team is clicked, the respective team players will be displayed. Then, you pass the
TeamID
parameter to the GetPlayerByTeam() function. Here, you should remember the name of the
team that has been selected, so that you can display it in the Repeater's header template.
9. Head back to the DataList control and edit the LinkButton control as follows:
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "TeamName") %>'
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "TeamID") %>'
id="TeamNameLink" style="color:darkred"
CommandName="ShowTeam" runat="server" />
10. Add the following to the DataList control tag:
<asp:DataList id="TeamList" runat="server"
OnItemCommand="TeamList_ItemCommand">
11. Add the following line of code outside all the methods in the page (this is a public variable):
string selectedTeam;
12. Finally, add the following code in the Code view of the page:
void TeamList_ItemCommand(object sender, DataListCommandEventArgs e)
{
if (e.CommandName == "ShowTeam")
{
LinkButton button = (LinkButton)e.CommandSource;
selectedTeam = button.Text;
PlayersList.DataSource =
GetPlayersByTeam(int.Parse((string)e.CommandArgument));
PlayersList.DataBind();
}
}
The page is now ready, so run the page in your browser. You should see the screen shown in

Figure 10-26:
348
Chapter 10
Figure 10-26
How It Works
We extended the first part of the example to incorporate an event handler that runs some specific code
when the name of a team is clicked. This code is used to populate the
Repeater control. Let's run
through it bit-by-bit:
<asp:DataList id="TeamList" runat="server"
OnItemCommand="TeamList_ItemCommand">
Adding the OnItemCommand property to the DataList control ensures that when the LinkButton
within the DataList is clicked, the ItemCommand event of the Repeater is raised and code in the
TeamList_ItemCommand() event handler is run. However, we need to pass the CommandArgument of
the
LinkButton, so we assign a CommandName property to the LinkButton:
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "TeamName") %>'
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "TeamID") %>'
id="TeamNameLink" style="color:darkred"
CommandName="ShowTeam" runat="server" />
In the event handler that runs when the ItemCommand event is fired, we can use the CommandArgument
property of the LinkButton:
void TeamList_ItemCommand(object sender, DataListCommandEventArgs e)
The event handler takes two parameters. e is an object of the type DataListCommandEventArgs. This
means that we can access certain properties of
e in our code that relate back to the control that originally
fired the event.
349
ASP.NET Server Controls

First, we can use the CommandName property of the LinkButton that was set to ShowTeam earlier:
if (e.CommandName == "ShowTeam")
{
We test whether the argument passed into the event handler has a CommandName set to ShowTeam. If it
does, we process some more code. The next two lines extract the name of the currently selected team.
This is used to set the value of the public string variable
selectedTeam:
LinkButton button = (LinkButton)e.CommandSource;
selectedTeam = button.Text;
Notice that we first have to create a new LinkButton object and use it to work with the properties of the
button that originally fired the method. We can identify the button that the request originated from by
using the
CommandSource property of the EventArgs (e) passed into the method. Once we have the
newly-created button object, we can access its
Text property.
The next section binds data to the
PlayersList Repeater control. Here, we access the
CommandArgument property of the e object, which is the CommandArgument property of the
LinkButton control that raised the event and is passed into the event handler. Because this argument is
passed across as a string and we require an integer, we must first specify that the argument is a string
and then convert it to an integer:
PlayersList.DataSource =
GetPlayersByTeam(int.Parse((string)e.CommandArgument));
PlayersList.DataBind();
}
}
We've seen how the event is handled. Now let's look at the control that is populated when the event
handler runs:
<asp:linkbutton
text='<%# DataBinder.Eval(Container.DataItem, "PlayerName") %>'

style="color:darkred" runat="server"
width="120"/>
&nbsp;&nbsp;
<asp:Label
text='<%# DataBinder.Eval(Container.DataItem, "PositionName") %>'
id="playerposition" runat="server" /><br/>
</ItemTemplate>
This control contains a LinkButton and a Label control in its ItemTemplate. We also define a header
and footer for our player list. Notice that the string value stored in the
SelectedTeam variable adds the
name of the team to the header of the control:
This event handler is quite complicated, but is a great example of how to handle
events raised by child controls (the
LinkButton) via a parent control (the DataList).
This is a process known as Event Bubbling, in which the events raised by the child
control bubble up to their parent control where they can be intercepted and handled.
350
Chapter 10
<headerTemplate>
Players in: <%= SelectedTeam %>
<hr color="#b0c4de" width="250px">
</headerTemplate>
<footerTemplate>
<hr color="#b0c4de" width="250px">
</footerTemplate>
</asp:Repeater>
The data for the items in the Repeater control comes from the GetPlayersByTeam() method:
System.Data.IDataReader GetPlayersByTeam(int teamID)
{
string connectionString =

"Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4; " +
"Data Source=C:\\BegASPNET11\\WroxUnited\\Database\\WroxUnited.mdb";
System.Data.IDbConnection dbConnection =
new System.Data.OleDb.OleDbConnection(connectionString);
This method contains the following large SQL statement to retrieve the data we're interested in:
string queryString =
"SELECT [Players].[PlayerName], [Positions].[PositionName] " +
"FROM [Players], [Positions], [PlayerTeam], [Teams] "+
"WHERE (([PlayerTeam].[PlayerID] = [Players].[PlayerID]) " +
"AND ([PlayerTeam].[Position] = [Positions].[PositionID]) " +
"AND ([PlayerTeam].[TeamID] = [Teams].[TeamID]) " +
"AND ([PlayerTeam].[TeamID] = @TeamID))";
This query is followed by some code that creates a Command object, and a parameter that passes the
TeamID.
System.Data.IDbCommand dbCommand = new System.Data.OleDb.OleDbCommand();
dbCommand.CommandText = queryString;
dbCommand.Connection = dbConnection;
System.Data.IDataParameter dbParam_teamID =
new System.Data.OleDb.OleDbParameter();
dbParam_teamID.ParameterName = "@TeamID";
dbParam_teamID.Value = teamID;
dbParam_teamID.DbType = System.Data.DbType.Int32;
dbCommand.Parameters.Add(dbParam_teamID);
Using a parameter ensures that the data passed into the method doesn't violate any
database constraints. For example, using a parameter removes our obligation to
escape text that would be invalid in a SQL statement, worry about inserting dates in
an unsuitable format, and so on. Catching data type errors in code before data is
passed to the database is a good way to work.
351
ASP.NET Server Controls

Finally, the data is read from the database and the DataReader object is returned by the function:
dbConnection.Open();
System.Data.IDataReader dataReader =
dbCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
return dataReader;
}
Our page is a bit more interesting now. Try clicking on different teams and see how the list of players
changes. You could also add more code that responds to the clicking of the link button in the
PlayersList control, which transfers the user to more information about the selected player, but we
recommend that you this yourselves.
The
Repeater control has produced results similar to the DataList control, and in many cases, you
might find yourself wondering which controls to use for different purposes. The end result is subtly
different. The
DataList control actually renders as an HTML table with cells for each item in the
template. The
Repeater is much less structured and simply spits back rendered versions of exactly what
was put into the templates with no extra hidden tags. This is why we had to add a line break to this
control to split the content onto different lines (we could also have used a separator template).
The only functionality difference between the two is that the
DataList can be used to edit data, whereas
the
Repeater is always read-only. For more information and some great examples, refer to Professional
ASP.NET 1.0, Special Edition, Wrox Press, ISBN 0-7645-4396-2.
Data-oriented controls have many different properties and events that we could discuss in depth here,
but it's time to move on and look at other topics. I highly recommend that you play and experiment with
these controls. Check out the rendered HTML in your browser using
View | Source
– you'll find that
it's a great way to understand how the rendering process works, and how you can optimize your code to

work with, not against, the ASP.NET compiler to produce the results you want.
You've now gained some experience of using a
DataList, a Repeater, and a LinkButton while putting
together one of the pages in the site. As you saw at the end of the previous example, the
DataList
control is a data rendering control. The LinkButton control, however, is a rich control. Let's find out more
about this type of control.
Rich Controls
Rich controls are compound in nature and provide extended functionality. In other words, rich controls
are typically combinations of two or more simple or intrinsic controls that compose a single functional
unit, for example, an
AdRotator control. Another distinguishing trait of these controls is that they don't
have a direct correlation to any single HTML control, even though they render to HTML when displayed
in the client browser. The following table discusses various rich controls and their functions:
352
Chapter 10
The nice thing about this family of rich controls is that they are just as easy to use as the other ASP.NET
server controls. They may boast of more features and properties, but the basic way of defining them and
interacting with them is programmatically the same as for all the other ASP.NET server controls.
The Calendar Control
The Calendar control produces some really complex HTML when rendered, but you'll find that adding
this control to a Web page is as simple as adding any other Web control! This control is designed to
present date information in the form of a calendar and allows a user to select a particular date. You can
configure the control via the
SelectionMode property to allow the user to select a range of dates. You
can also completely customize how this control is presented using the many different properties that it
has access to. Let's take a quick look at some of these properties:
FirstDayOfWeek=[Default|Monday|Tuesday|Wednesday|
Thursday|Friday|Saturday|Sunday]
The FirstDayOfWeek property enables you to choose the day of the week your calendar starts from.

Some calendars default to Sunday as the first day of the week. For business purposes, however, it's more
practical to have the week starting from Monday.
SelectionMode=[None|Day|DayWeek|DayWeekMonth]
By default, the Calendar control's SelectionMode defaults to Day. This is useful when you want your
user to be able to select only a single day. However, you can select multiple days by setting the
SelectionMode property to either DayWeek, which will allow you to select a single day or an entire
week, or
DayWeekMonth, which will allow you to select a single day, an entire week, or the entire month.
Control Purpose
AdRotator
Displays advertisement banners on a Web form. The displayed
advertisement is randomly changed each time the form is loaded or
refreshed.
Calendar
Displays a one-month calendar for viewing/selecting a date, month, or
year.
CheckBoxList
Multiple-selection checkbox group; can be dynamically generated with
data binding.
ImageButton
Provides a clickable image with (optional) access to the clicked
coordinates to support image-map functionality.
LinkButton
Hyperlink-style button that posts back to the page of origin. We've seen
a couple of these in action already.
RadioButtonList
Mutually exclusive radio button group. Can be dynamically generated
with data binding.
353
ASP.NET Server Controls

The Calendar control's SelectMonthText and SelectWeekText properties enable you to customize
the HTML that is rendered at the browser – use these properties if you're really going for a customized
look:
SelectMonthText="HTML text"
SelectWeekText="HTML text"
You need not define all of the properties of the ASP.NET Calendar control to display the control. In fact,
the following declaration will create an efficient ASP.NET
Calendar server control that looks good and
displays quite well:
<asp:Calendar id="MyCalendarControl" runat="server" />
When delivered to the client browser, the result is an HTML calendar as shown in Figure 10-27 that
enables you to navigate through the various days, months, and years:
Figure 10-27
Take a look at the HTML that ASP.NET produced to create this page – over 100 lines of HTML and
JavaScript, while you wrote only a single line!
Let's now add a calendar that will highlight the days on which matches are scheduled and then display
the details of those matches when that date is selected.
Try It Out Wrox United – Default.aspx, Part 2, the Event Calendar
1.
Reopen Default.aspx and add the following HTML table in the HTML view to change the
layout of the new and improved front page:
<p>
Welcome to the Wrox United Website! Please select one
354
Chapter 10
of the following:
</p>
<table style="WIDTH: 800px">
<tr>
<td style="WIDTH: 200px">

<p>
<asp:HyperLink id="lnkTeams" runat="server"
NavigateUrl="Default.aspx">
Teams
</asp:HyperLink>
</p>

<p>
<asp:HyperLink id="lnkResults" runat="server"
NavigateUrl="Default.aspx">
Results
</asp:HyperLink>
</p>
</td>
<td style="VERTICAL-ALIGN: top; width: 350px;">&nbsp;</td>
<td style="VERTICAL-ALIGN: top; width: 250px;"></td>
</tr>
</table>
</form>
2. Switch to Design view and drag a Calendar control into the third cell of the table, as shown in
Figure 10-28. Name this calendar
EventCalendar:
355
ASP.NET Server Controls
Figure 10-28
3. Click the lightning bolt in the Properties pane to display the available events, and double-click
on the
DayRender() event's textbox to be taken back to Code view, where you need to enter
more code. Before filling in the
DayRender() event handler, let's take a moment to consider

what we're trying to achieve. We want to highlight the days of the games and store dates of the
games in the
Games table in the database. If we want to display more information about a
particular day, we also need to store the
GameID so that we can again query the database later.
4. The next task is to add another DataReader to this page using the wizard, and then store that
data in a Hashtable (where we can store details of dates and games in key-value pairs, as we saw
in Chapter 8). At the top of the page, add the following line of code:
System.Collections.Hashtable DateList;
5. Drag a SELECT data wizard onto the page. Select the GameID and Date fields from the Games
table, save this function with the name Dates(), and specify that it returns a DataReader
object:
System.Data.IDataReader Dates()
{
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " +
356
Chapter 10

×