
Beginning ASP.NET 2.0 With CSharp (2006) [eng]
.pdf
Chapter 6
Figure 6-15
6.Switch to Source View and locate the ImageButton control. Change the declaration so that it looks like this:
<asp:ImageButton ID=”ImageButton1” runat=”server”
OnClick=”ImageButton_Click” ImageUrl=”~/images/AddToCart.gif” />
7.Open the code file, Default.aspx.cs, and add the following code, just before the End Class statement:
protected void ImageButton_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
TextBox1.Text = “You clicked the ImageButton at position “+ e.X.ToString() + “,” + e.Y.ToString();
}
8.Press F5 to run the page. Click several times in the ImageButton, moving the cursor so that you click in a different position. Notice how the coordinates of where you click are shown in the text box.
How It Works
The important bit of how this works is in the Source View, where the ImageButton control is defined. Here you added the following to it:
OnClick=”ImageButton_Click”
This tells the control that for the Click event you want to run the procedure called ImageButton_Click — this is the same as for the standard button you used earlier. Within the code file, the event procedure declaration is similar, but the second parameter is different from the type you’ve seen before:
protected void ImageButton_Click(object sender, System.Web.UI.ImageClickEventArgs e)
For the Button, the second parameter was System.EventArgs, but for the ImageButton it is System.Web.UI.ImageClickEventArgs. Remember that the second parameter can be used by ASP.NET to pass extra information into the event procedure, but for Button controls there was no extra
188

Events and Code
information. For an ImageButton there is extra information, so the parameter is different — in this case it contains the X and Y coordinates of where on the image the mouse was clicked. You simply display these coordinates in the text box. You don’t actually need these coordinates, but this is a great example of parameters having extra information.
A parameter name other than System.EventArgs is actually a good indication that additional information may be available to you in the event procedure. You can find out what that information is by simply typing e. in the code window and looking at the IntelliSense that pops up.
Events Aren’t Triggered by Users Only
So far in this chapter the events you’ve seen have been explicitly generated by the user, by way of clicking a button. Some events, however, are generated in other ways. Some are indirectly generated by the user, perhaps by way of updating some data, and others are generated directly by ASP.NET. You can use the events regardless of how they are generated, and in this section you see how you can do this.
You’re going to create some events from data in a database, and although data has not been covered yet, it’s the events that are important. First, have a look at the news items on the Wrox United site (see Figure 6-16), found under the About News menu item.
Figure 6-16
189

Chapter 6
Here you can see that not all of the news items have a picture. In the following Try It Out, you see how the news items can be customized, by responding to events generated by controls that fetch data. You’ll make sure that an image is only visible when there is a picture associated with the news item.
Try It Out |
Data Events |
1.Close any open browser windows.
2.In Visual Web Developer open the DataEvents.aspx file from the Chapter06 web site.
3.Right-click the mouse button anywhere on the page, and select View in Browser from the menu that appears. You’ll see a screen similar to Figure 6-17.
Notice that not all of the news items have images. For those that don’t there is a small image with a red cross in it, indicating that the image is missing; this is the default. You need to modify the page to use events, so that if there is no image for the news item, that red cross isn’t shown.
4.Close the browser and switch to Design View in Visual Web Developer.
5.Select the DataList control. There are only two controls on the page: SqlDataSource and DataList. The DataList control is bound to a database, so it shows Databound items — simply click anywhere on this control to select it.
Figure 6-17
190

Events and Code
6.From the Properties box, select the events and double-click into the ItemDataBound event. Don’t enter any text, just double-click, and this will open the code editor and create the empty event procedure for you.
7.Add the following code in the empty event procedure:
DataRowView row;
Image img;
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
row = (DataRowView)e.Item.DataItem;
if (row[“PictureURL”].ToString().Trim() == “”)
{
img = (Image)e.Item.FindControl(“NewsImage”); img.Visible = false;
}
}
8.Save the pages and switch back to the Design View of the page. Right-click the page and select the View in Browser menu item to view the page in the browser. Notice how the red cross images have disappeared.
How It Works
Before looking at the code you need to understand how HTML handles images. The image is created with an img tag, like so:
<img src=”ImageName.gif”></img>
When the browser receives this HTML it displays the image, or that red cross if the image isn’t found. When you use server controls for images, you use an Image control:
<asp:Image ImageUrl=”ImageName.gif” runat=”server” id=”Image1”></Image>
This renders the same HTML as the first example. So if there’s no physical file you get that red cross, which is exactly what’s happening on this page; you need some way to not show the red cross image if there’s no picture associated with the news story.
In the DataEvents.aspx page you use an Image server control, but the value for the ImageUrl property is fetched from a database. Databases are covered in the next two chapters, so it’s not important to know how this works just yet. The important point is to realize that as each row of data (a news item) is fetched from the database it is bound to the DataList, which means that there will be an item in the DataList for each row in the table fetched from the database. Each row of data contains different bits of the news: the title, the description, and what you’re really interested in for this example, the picture name. But not every news item has a picture, so you have to check to see if the database has a picture and if it doesn’t, you make the Image control invisible. Take a look at the code that makes this possible.
191

Chapter 6
First, you have the ItemDataBound event itself:
protected void DataList1_ItemDataBound(object sender, System.Web.UI.WebControls.DataListItemEventArgs e)
This event is raised when a row from the database is bound to a server control. Like the Click event of the ImageButton, the ItemDataBound event of the DataList supplies extra information to the event procedure in the form of the second parameter. This contains information about the row being bound, and contains a property called DataItem, which itself contains three properties:
DataItem: The actual data item from the database.
ItemIndex: The index number of the item being bound. This starts at 0 and increments by one for each row.
ItemType: The type of the item in the DataList. This will be one of the following:
AlternatingItem, EditItem, Footer, Header, Item, Pager, SelectedItem, or Separator.
The ItemType is used to determine what type of row item you are on. For example, if data is being bound into the header row, the ItemType would be Header. For the actual rows in this example, the ItemType will be Item or AlternatingItem (for each row and every other row). So your code, shown here, simply checks the ItemType, so you only work with the rows you are interested in:
If (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
Next you can use the ItemType to access the actual data being bound to the Image control, so you can check to see if there is any data for the image. First, you extract the actual row of data — don’t worry about the exact details of this code; data and data conversion are covered in the next few chapters. What’s important to remember is that e.Item.DataItem is the actual data from the database for this row, and you check to see whether the PictureUrl column is empty:
row = (DataRowView)e.Item.DataItem;
if (row[“PictureUrl”].ToString().Trim() == “”)
If the PictureUrl column is empty, you want to access the Image control and make it invisible. Here you again use e.Item, but this time to find the Image control (NewsImage), and set its Visible property to false:
img = (Image)e.Item.FindControl(“NewsImage”); img.Visible = false;
Several things in this example have not been explained fully because they are covered in more detail later in the book. Data binding and databases are covered in Chapter 7, and data conversion and casting, and the use of FindControl are covered in Chapter 9. You don’t need to understand how these work at the moment, because the important thing is to know what is possible. In this case, you are seeing that an event is raised when an item from the database is bound to a server control. This event provides information about the underlying data and the row on the server control, thus giving you a lot of information.
This technique is also used on the menu. Chapter 3 looked at the navigation controls such as the Menu and SiteMapPath controls. One of the issues we have with the Wrox United web site is that we wanted the
192

Events and Code
SiteMapPath on every page, which means that every page has to be in the SiteMap file as XML nodes. However, we don’t want all of the pages to appear in the Menu. For example, we don’t want users to navigate directly to the Checkout page, because we only want them to access it from the Shopping Cart page. The problem we have is that we can have an item that appears in the SiteMap and SiteMapPath, but that doesn’t appear in the Menu — the navigation framework doesn’t cater for that situation. So we have to cheat.
What you do is use the MenuItemDataBound event in the master page (site.Master), as shown here:
protected void MyMenu_MenuItemDataBound(object sender, System.Web.UI.WebControls.MenuEventArgs e)
{
string text = e.Item.Text;
if (text == “Checkout” || text == “Shop Item” || text == “Shopping Cart”) e.Item.Parent.ChildItems.Remove(e.Item);
}
As each menu item is taken from the SiteMap file and bound to the menu the MenuItemDataBound event is raised. Within this event procedure we check to see if the menu text is one of the pages we don’t want to show, and if it is we remove the item from the menu. This means that the item still retains its place in the navigation structure, but that it won’t show on the menu.
So you can see that events raised by ASP.NET are extremely useful. Despite the fact ASP.NET takes care of the data binding and display of data for us, we still have access to what’s happening. The next section looks at another example, where events are raised indirectly by the user.
Indirect Events
Indirect events are raised by ASP.NET, but because of some action that the user took. For example, have a look at one of the administration pages, where the team owner can change the players in the squad, as shown in Figure 6-18.
Here there are two visible controls: the GridView at the top, showing all players, and the DetailsView at the bottom where the player details are edited. One of the things you have to do is make sure that the GridView is updated when the player details are changed. The following Try It Out shows how you can do this.
Try It Out |
Indirect Events |
1.In the Chapter06 web site in Visual Web Developer, open the EditSquad.aspx page.
2.Click the right mouse button and select View in Browser from the menu.
193

Chapter 6
Figure 6-18
Figure 6-19
194

Events and Code
3.View the player details by clicking the More details link — pick Chris Christopher the Left Back.
4.Click the Edit link to allow the player details to be changed. Change his position from Left Back to Goalkeeper and click Update. Notice how the details show him as Goalkeeper, but the grid still shows him as Left Back, as in Figure 6-19.
You need to change this to make sure that the grid is updated with the new details.
5.Close the browser window and return to Visual Web Developer.
6.Create an event procedure for the Updated event of the Details data source, by selecting the DetailsDataSource control and double-clicking into the Updated event when viewing the events list in the properties window.
7.Add the following line of code into the empty event procedure:
GridView1.DataBind();
8.Save and close the code file.
9.From the web page, view the page in the browser and repeat the update process, changing the Position of Chris Christopher to Striker. Notice that when you click Update to save the changes the grid also changes.
How It Works
This code is extremely simple, and even though it relies on data binding, it is easy to understand. The key is that the page uses a SqlDataSource object, which is responsible for fetching the data from the database and making it available to the grid to display. The SqlDataSource control is just like other ASP.NET server controls, except that it doesn’t actually display anything. So although it’s on the page, nothing is shown to the user.
As well as providing data for the grid to show, the SqlDataSource also deals with data edits — inserting new rows, and updating and deleting existing rows, and for each of these actions there are events. One of these events is the Updated event, which is raised when the data is updated. So when you click the Update link, the SqlDataSource updates the database, and then raises the Updated event. The code in the Updated event simply tells the grid to rebind its data — to fetch it again and redisplay it. So what you’re doing is using multiple controls, with a chain of actions that result in an event, as seen in Figure 6-20.
You can see that although you can easily construct pages by just dropping controls onto a page and configuring properties, knowing how these controls work is important. Without knowing that the update of the DetailsView generated a similar event for the data source, you might spend time trying to work out which event on the DetailsView could be used to refresh the grid.
195

Chapter 6
Date Left
Update Cancel
Data Saved
SqlDataSource - DetailsDataSource
Update
GridView1.DataBind()
FirstName |
LastName |
Position |
PictureURL |
Date |
Date |
Date |
|
|
|
|
Joined |
Left |
Left |
Aaron |
Aaronson |
Goalkeeper |
aaronson.jpg |
02-Jan-00 |
|
More details |
|
|
|
|
|
|
|
Bill |
Barker |
Goalkeeper |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
Chris |
Christopher |
Right Back |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
Dave |
Dickenson |
Right Back |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
Eric |
Edmundson |
Central |
aaronson.jpg |
|
|
More details |
|
|
Defender |
|
|
|
|
|
|
|
|
|
|
|
Fred |
Fortinghoe- |
Midfield |
aaronson.jpg |
|
|
More details |
|
Smythe |
|
|
|
|
|
|
|
|
|
|
|
|
Gerry |
Gudminster |
Midfield |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
Harry |
Hunter |
Midfield |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
Ian |
Inderson |
Left Wing |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
Jerry |
Johnson |
Right Wing |
aaronson.jpg |
|
|
More details |
|
|
|
|
|
|
|
1_2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
Figure 6-20
Canceling Events
So far in this chapter you’ve seen controls raise single events. Both the Button control and the ImageButton control raise a Click event, whereas other controls raise other events. One thing you have probably noticed is that the controls have quite a lot of events that could be raised, and you may not have realized that a single action can raise multiple events. For example, when updating data there is both an Updating and an Updated event. Likewise, there are pairs of events for adding new data
196

Events and Code
(Inserting/Inserted) and for data being deleted (Deleting/Deleted). The present tense event (Inserting, for example) is raised as the action is occurring, whereas the past tense event (such as Deleted) is raised after the event. For example, when deleting a row, the Deleting event is raised just before the row is deleted, and the Deleted event is raised after the event is raised.
For some events, the fact that they are raised before the actual action takes place gives you the opportunity to cancel the event. For example, consider the EditSquad.aspx file, where the team owner can change the squad. One of the things the owner wants is to make sure that any players that left during the playing season remain in the database — so you can’t delete players between August 20 and May 31. To enable this, you need to allow deletion of players, but not within those dates. Give this a go in the next Try It Out.
Try It Out |
Canceling Events |
1.Open the EditSquad.aspx file in the Visual Web Developer designer, and add a Label control at the very end of the page.
2.Set the ID of the Label control to Message, and clear the Text property.
3.Select the DetailsDataSource control, and on the events list double-click into the box next to the Deleting event to have the event procedure created for you.
4.In the empty event procedure, add the following code:
DateTime today = DateTime.Now; int startYear;
int endYear; DateTime seasonStart; DateTime seasonEnd;
if (today.Month > 5)
{
startYear |
= today.Year; |
|
endYear = today.Year + 1; |
|
|
} |
|
|
else |
|
|
{ |
|
|
startYear = today.Year - 1; |
|
|
endYear = today.Year; |
|
|
} |
|
|
seasonStart = new DateTime(startYear, 8, 20); |
// 20th August |
|
seasonEnd = new DateTime(endYear, 5, 31); |
// 31st May |
if (today >= seasonStart && today <= seasonEnd)
{
e.Cancel = true;
Message.Text = “Cannot delete players during the season”;
}
else
{
GridView1.DataBind(); Message.Text = “”;
}
197