WEB STANDARDS NOTE The AddressForm User control does not use an HTML table to lay out its controls.. CHAPTER 7 Creating Custom Controls with User Controls Listing 7.12 randomly displays
Trang 1CHAPTER 7 Creating Custom Controls with User Controls
AssociatedControlID=”txtCity”
Runat=”server” />
</div>
<div class=”addressField”>
<asp:TextBox
ID=”txtCity”
Runat=”server” />
<asp:RequiredFieldValidator
ID=”reqCity”
Text=”(required)”
ControlToValidate=”txtCity”
Runat=”server” />
</div>
<br class=”clear” />
<div class=”addressLabel”>
<asp:Label
ID=”lblState”
Text=”State:”
AssociatedControlID=”txtState”
Runat=”server” />
</div>
<div class=”addressField”>
<asp:TextBox
ID=”txtState”
Runat=”server” />
<asp:RequiredFieldValidator
ID=”reqState”
Text=”(required)”
ControlToValidate=”txtState”
Runat=”server” />
</div>
<br class=”clear” />
<div class=”addressLabel”>
<asp:Label
ID=”lblPostalCode”
Text=”Postal Code:”
AssociatedControlID=”txtPostalCode”
Runat=”server” />
</div>
<div class=”addressField”>
<asp:TextBox
ID=”txtPostalCode”
Trang 2Runat=”server” />
<asp:RequiredFieldValidator
ID=”RequiredFieldValidator1”
Text=”(required)”
ControlToValidate=”txtPostalCode”
Runat=”server” />
</div>
<br class=”clear” />
</fieldset>
The AddressForm control contains form controls for entering your street, city, state, and
postal code Each of these fields is validated by a RequiredFieldValidator control Finally,
the AddressForm includes a Label that can provide a title for the control
The AddressForm exposes all its form fields with properties The control includes public
Street, City, State, and PostalCode property, which you can read from the containing page
The page in Listing 7.11 illustrates how you can use the AddressForm control in a page
LISTING 7.11 Checkout.aspx
<%@ Page Language=”C#” %>
<%@ Register TagPrefix=”user” TagName=”AddressForm” Src=”~/AddressForm.ascx” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
protected void btnSubmit_Click(object sender, EventArgs e)
{
// Show Billing Address Form Results
ltlResults.Text = “<br />Billing Street: “ + AddressForm1.Street;
ltlResults.Text += “<br />Billing City: “ + AddressForm1.City;
ltlResults.Text += “<br />Billing State: “ + AddressForm1.State;
ltlResults.Text += “<br />Billing Postal Code: “ + AddressForm1.PostalCode;
ltlResults.Text += “<br /><br />”;
// Show Shipping Address Form Results
ltlResults.Text += “<br />Shipping Street: “ + AddressForm2.Street;
ltlResults.Text += “<br />Shipping City: “ + AddressForm2.City;
ltlResults.Text += “<br />Shipping State: “ + AddressForm2.State;
ltlResults.Text += “<br />Shipping Postal Code: “ + AddressForm2.PostalCode;
}
</script>
Trang 3CHAPTER 7 Creating Custom Controls with User Controls
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<style type=”text/css”>
html
{
background-color:silver;
font:14px Georgia,Serif;
}
.content
{
background-color:white;
width:600px;
margin:auto;
padding:20px;
}
.addressLabel
{
float:left;
width:100px;
padding:5px;
text-align:right;
}
.addressField
{
float:left;
padding:5px;
}
.clear
{
clear:both;
}
</style>
<title>Checkout</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div class=”content”>
<user:AddressForm
id=”AddressForm1”
Title=”Billing Address”
Runat=”server” />
<br />
Trang 4<user:AddressForm
id=”AddressForm2”
Title=”Shipping Address”
Runat=”server” />
<br />
<asp:Button
ID=”btnSubmit”
Text=”Submit Form”
OnClick=”btnSubmit_Click”
Runat=”server” />
<hr />
<asp:Literal
id=”ltlResults”
Runat=”server” />
</div>
</form>
</body>
</html>
The page in Listing 7.11 contains two instances of the AddressForm control: a Billing
Address and Shipping Address When you click the Button control, the address information
is retrieved from the AddressForm controls and displayed in a Literal control (In a real
application, you would grab the data and store it in a database.)
WEB STANDARDS NOTE
The AddressForm User control does not use an HTML table to lay out its controls You
should strive to avoid using tables except when displaying tabular information Instead,
Cascading Style Sheet (CSS) rules are used to position the form elements
AJAX and User Controls
Ajax (Asynchronous JavaScript and XML) enables you to update content in a page without
posting the page back to the server Behind the scenes, AJAX uses the XMLHttp ActiveX
component (in the case of Microsoft Internet Explorer 6.0) or the XMLHttpRequest
intrin-sic browser object (in the case of other browsers such as FireFox and Internet Explorer 8.0)
We explore the topic of Ajax in depth in Part IX, “ASP.NET AJAX.” In this section, I want
to provide you with a quick sample of using Ajax with a User control The User control in
Trang 5CHAPTER 7 Creating Custom Controls with User Controls
Listing 7.12 randomly displays one of three quotations The quotation is updated
auto-matically every 5 seconds (see Figure 7.4)
FIGURE 7.4 Using AJAX to display a random quotation
LISTING 7.12 RandomQuotation.ascx
<%@ Control Language=”C#” ClassName=”RandomQuotation” %>
<%@ Import Namespace=”System.Collections.Generic” %>
<script runat=”server”>
void Page_Load()
{
List<string> quotes = new List<string>();
quotes.Add(“All paid jobs absorb and degrade the mind Aristotle”);
quotes.Add(“No evil can happen to a good man, either in life or after death
Plato”);
quotes.Add(“The only good is knowledge and the only evil is ignorance
Plato”);
Random rnd = new Random();
lblQuote.Text = quotes[rnd.Next(quotes.Count)];
}
</script>
Trang 6<asp:ScriptManager ID=”sm1” runat=”server” />
<asp:Timer ID=”Timer1” Interval=”5000” runat=”server” />
<asp:UpdatePanel ID=”up1” runat=”server”>
<Triggers>
<asp:AsyncPostBackTrigger ControlID=”Timer1” />
</Triggers>
<ContentTemplate>
<div class=”quote”>
<asp:Label
id=”lblQuote”
Runat=”server” />
</div>
</ContentTemplate>
</asp:UpdatePanel>
A random quotation is assigned to the Label control in the Page_Load() method in Listing
7.12 The Label control is contained in an UpdatePanel control The UpdatePanel marks
an area of the page that is refreshed without a postback (an Ajax zone) The UpdatePanel
control is associated with a Timer control The Timer control causes the UpdatePanel to
refresh its content every 5 seconds (an interval of 5,000 milliseconds)
The page in Listing 7.13 illustrates how you can use the RandomQuotation User control It
contains the User control and also displays the current time
LISTING 7.13 ShowRandomQuotation.aspx
<%@ Page Language=”C#” %>
<%@ Register TagPrefix=”user” TagName=”RandomQuotation”
Src=”~/RandomQuotation.ascx” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<style type=”text/css”>
.quote
{
width:200px;
padding:20px;
border:Dotted 2px orange;
background-color:#eeeeee;
font:16px Georgia,Serif;
}
</style>
<title>Show Random Quotation</title>
Trang 7CHAPTER 7 Creating Custom Controls with User Controls
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<%= DateTime.Now %>
<br />
<user:RandomQuotation
id=”RandomQuotation1”
Runat=”server” />
</div>
</form>
</body>
</html>
The random quotation is updated, but the time on the page does not change Only the
area of the page that contains the random quotation is updated
Dynamically Loading User Controls
You can dynamically load a User control at runtime and display it in a page Imagine, for
example, that you want to display different featured products randomly on the home page
of your website However, you want to display each featured product with a completely
different layout In that case, you can create a separate User control for each product and
load one of the User controls randomly at runtime
You load a User control with the Page.LoadControl() method, which returns an instance
of the Control class that you can add to a page Typically, you add the User control to a
PlaceHolder control that you have declared on the page
NOTE
The PlaceHolder control was designed to do absolutely nothing It simply acts as a
placeholder on the page where you can add other controls
For example, the page in Listing 7.14 randomly loads one of the controls from the
FeaturedProducts folder and adds the control to the page
Trang 8LISTING 7.14 ShowFeaturedProduct.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.IO” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
const string randomFolder = “~/FeaturedProducts”;
protected void Page_Load(object sender, EventArgs e)
{
string featuredProductPath = GetRandomProductPath();
Control featuredProduct = Page.LoadControl(featuredProductPath);
PlaceHolder1.Controls.Add(featuredProduct);
}
private string GetRandomProductPath()
{
Random rnd = new Random();
string[] files = Directory.GetFiles(MapPath(randomFolder), “*.ascx”);
string featuredProductPath =
➥Path.GetFileName(files[rnd.Next(files.Length)]);
return Path.Combine(randomFolder, featuredProductPath);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Featured Products</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:PlaceHolder
id=”PlaceHolder1”
Runat=”server” />
</div>
</form>
</body>
</html>
Trang 9CHAPTER 7 Creating Custom Controls with User Controls
Using the Reference Directive
When you load a User control with the Page.LoadControl() method, the User control is
returned as an instance of the System.Web.UI.Control class This means that if the User
control includes any custom properties, the properties aren’t available when you
dynami-cally load the User control
If you dynamically load a User control, you need to cast the control to the correct type
before you can access any of the control’s custom properties To get a reference to a User
control’s type, you must use the <%@ Reference %> directive
For example, imagine that you need to create a form that displays different questions
depending on the answers that a user provides for previous questions In that case, you
can dynamically load different User controls that contain the different sets of questions
For example, the page in Listing 7.15 contains a survey form The first question asks you
whether you currently use ASP Classic or ASP.NET Depending on your answer, the
remain-der of the form displays different questions (see Figure 7.5)
FIGURE 7.5 Displaying a survey form with dynamically loaded questions
Trang 10LISTING 7.15 WebSurvey.aspx
<%@ Page Language=”C#” %>
<%@ Reference Control=”~/ASPSurvey.ascx” %>
<%@ Reference Control=”~/ASPNetSurvey.ascx” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
private Control _survey = null;
void Page_Load()
{
switch (ddlLanguage.SelectedIndex)
{
case 1:
_survey = Page.LoadControl(“ASPSurvey.ascx”);
break;
case 2:
_survey = Page.LoadControl(“ASPNetSurvey.ascx”);
break;
}
if (_survey != null)
PlaceHolder1.Controls.Add(_survey);
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
switch (ddlLanguage.SelectedIndex)
{
case 1:
ASPSurvey aspResults = (ASPSurvey)_survey;
ltlResults.Text = “<h1>ASP Survey</h1>”;
ltlResults.Text += “<br />Know slow? “ +
➥aspResults.KnowSlow.ToString();
ltlResults.Text += “<br />Know outdated? “ +
➥aspResults.KnowOutdated.ToString();
break;
case 2:
ASPNetSurvey aspNetResults = (ASPNetSurvey)_survey;
ltlResults.Text = “<h1>ASP.NET Survey</h1>”;
ltlResults.Text += “<br />Know fast? “ +
➥aspNetResults.KnowFast.ToString();
ltlResults.Text += “<br />Know newest? “ +
➥aspNetResults.KnowNewest.ToString();