ptg 304 </div> </form> </body> </html> You need to be aware of one important limitation when registering a User control in the web configuration file. A User control cannot be located in the same folder as a page that uses it. For that reason, you should create all your User controls in a subfolder. Exposing Properties from a User Control The RandomImage User control always displays an image from the Images folder. It would be nice if you could specify the name of the folder that contains the images so that you could use different folder paths in different applications. You can do this by exposing a property from the RandomImage User control. The modified RandomImage control in Listing 7.5, named PropertyRandomImage, exposes a property named ImageFolderPath. LISTING 7.5 PropertyRandomImage.ascx <%@ Control Language=”C#” ClassName=”PropertyRandomImage” %> <%@ Import Namespace=”System.IO” %> <script runat=”server”> private string _imageFolderPath = “~/Images”; public string ImageFolderPath { get { return _imageFolderPath; } set { _imageFolderPath = value; } } void Page_Load() { string imageToDisplay = GetRandomImage(); imgRandom.ImageUrl = Path.Combine(_imageFolderPath, imageToDisplay); lblRandom.Text = imageToDisplay; } private string GetRandomImage() { Random rnd = new Random(); string[] images = Directory.GetFiles(MapPath(imageFolderPath), “*.jpg”); string imageToDisplay = images[rnd.Next(images.Length)]; return Path.GetFileName(imageToDisplay); CHAPTER 7 Creating Custom Controls with User Controls From the Library of Wow! eBook ptg 305 Creating User Controls 7 } </script> <asp:Image id=”imgRandom” Width=”300px” Runat=”server” /> <br /> <asp:Label id=”lblRandom” Runat=”server” /> After you expose a property in a User control, you can set the property either declaratively or programmatically. The page in Listing 7.6 sets the ImageFolderPath property declaratively. LISTING 7.6 ShowDeclarative.aspx <%@ Page Language=”C#” %> <%@ Register TagPrefix=”user” TagName=”PropertyRandomImage” Src=”~/PropertyRandomImage.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”> <title>Show Declarative</title> </head> <body> <form id=”form1” runat=”server”> <div> <user:PropertyRandomImage ID=”PropertyRandomImage1” ImageFolderPath=”~/Images2” Runat=”server” /> </div> </form> </body> </html> The PropertyRandomImage User control in Listing 7.6 includes an ImageFolderPath prop- erty. When you request the page, the random images are retrieved from the Images2 folder. From the Library of Wow! eBook ptg 306 VISUAL WEB DEVELOPER NOTE Any properties that you add to a User control appear in both Intellisense and the Property window. The page in Listing 7.7 demonstrates how you can set the ImageFolderPath programmatically. LISTING 7.7 ShowProgrammatic.aspx <%@ Page Language=”C#” %> <%@ Register TagPrefix=”user” TagName=”PropertyRandomImage” Src=”~/PropertyRandomImage.ascx” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <script runat=”server”> protected void Page_Load(object sender, EventArgs e) { PropertyRandomImage1.ImageFolderPath = “~/Images2”; } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Programmatic</title> </head> <body> <form id=”form1” runat=”server”> <div> <user:PropertyRandomImage ID=”PropertyRandomImage1” Runat=”server” /> </div> </form> </body> </html> The page in Listing 7.7 includes a Page_Load() event handler. This handler programmati- cally sets the ImageFolderPath to the value Images2. CHAPTER 7 Creating Custom Controls with User Controls From the Library of Wow! eBook ptg 307 Creating User Controls 7 Exposing Events from a User Control You can expose custom events from a User control. After you expose the event, you can handle the event in the page that contains the User control. Exposing events is useful when you need to pass information up to the containing page. Imagine, for example, that you want to create a custom tab strip with a User control. When a user clicks a tab, you want to change the content displayed in the page (see Figure 7.2). FIGURE 7.2 Displaying a tab strip with a User control. The User control in Listing 7.8 contains the code for a simple tab strip. LISTING 7.8 TabStrip.ascx <%@ Control Language=”C#” ClassName=”TabStrip” %> <%@ Import Namespace=”System.Collections.Generic” %> <script runat=”server”> public event EventHandler TabClick; /// <summary> /// The index of the selected tab /// </summary> From the Library of Wow! eBook ptg 308 public int SelectedIndex { get { return dlstTabStrip.SelectedIndex; } } /// <summary> /// Create the tabs /// </summary> void Page_Load() { if (!Page.IsPostBack) { // Create the tabs List<string> tabs = new List<string>(); tabs.Add(“Products”); tabs.Add(“Services”); tabs.Add(“About”); // Bind tabs to the DataList dlstTabStrip.DataSource = tabs; dlstTabStrip.DataBind(); // Select first tab dlstTabStrip.SelectedIndex = 0; } } /// <summary> /// This method executes when a user clicks a tab /// </summary> protected void dlstTabStrip_SelectedIndexChanged(object sender, EventArgs e) { if (TabClick != null) TabClick(this, EventArgs.Empty); } </script> <asp:DataList id=”dlstTabStrip” RepeatDirection=”Horizontal” OnSelectedIndexChanged=”dlstTabStrip_SelectedIndexChanged” CssClass=”tabs” ItemStyle-CssClass=”tab” SelectedItemStyle-CssClass=”selectedTab” Runat=”server”> <ItemTemplate> CHAPTER 7 Creating Custom Controls with User Controls From the Library of Wow! eBook ptg 309 Creating User Controls 7 <asp:LinkButton id=”lnkTab” Text=’<%# Container.DataItem %>’ CommandName=”Select” Runat=”server” /> </ItemTemplate> </asp:DataList> The tab strip is created with the help of a DataList control. The DataList control displays links for each of the items created in the Page_Load() event handler. The TabStrip control exposes an event named TabClick. This event is raised in the dlstTabStrip_SelectedIndexChanged() event handler when a user clicks a tab. The page in Listing 7.9 uses the TabStrip control to display different content depending on the tab selected. LISTING 7.9 ShowTabStrip.aspx <%@ Page Language=”C#” %> <%@ Register TagPrefix=”user” TagName=”TabStrip” Src=”~/TabStrip.ascx” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <script runat=”server”> protected void TabStrip1_TabClick(object sender, EventArgs e) { MultiView1.ActiveViewIndex = TabStrip1.SelectedIndex; } </script> <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; } .tabs a { color:blue; text-decoration:none; font:14px Arial,Sans-Serif; } .tab { From the Library of Wow! eBook ptg 310 CHAPTER 7 Creating Custom Controls with User Controls background-color:#eeeeee; padding:5px; border:Solid 1px black; border-bottom:none; } .selectedTab { background-color:white; padding:5px; border:Solid 1px black; border-bottom:none; } .views { background-color:white; width:400px; border:Solid 1px black; padding:10px; } </style> <title>Show TabStrip</title> </head> <body> <form id=”form1” runat=”server”> <div> <user:TabStrip ID=”TabStrip1” OnTabClick=”TabStrip1_TabClick” Runat=”Server” /> <div class=”views”> <asp:MultiView id=”MultiView1” ActiveViewIndex=”0” Runat=”server”> <asp:View ID=”Products” runat=”server”> <h1>Products</h1> We sell a variety of useful products </asp:View> <asp:View ID=”Services” runat=”server”> <h1>Services</h1> We offer a number of services From the Library of Wow! eBook ptg 311 Creating User Controls 7 </asp:View> <asp:View ID=”About” runat=”server”> <h1>About</h1> We were the first company to offer products and services </asp:View> </asp:MultiView> </div> </div> </form> </body> </html> The page in Listing 7.9 includes an event handler for the TabStrip control’s TabClick event. When you click a tab, the index of the selected tab is retrieved from the tab strip, and the View control with the matching index displays. VISUAL WEB DEVELOPER NOTE You c an add a TabClick event handler to the TabStrip control by selecting the TabStrip control from the top-left drop-down list and selecting the TabClick event from the top-right drop-down list. NOTE The ASP.NET Framework includes a Menu control that you can use to create both tab- strips and pop-up menus. This control is discussed in Chapter 4, “Using the Rich Controls,” and Chapter 22, “Using the Navigation Controls.” Creating an AddressForm Control Let’s end this section by creating a generally useful Web User control. We build an AddressForm User control that you can reuse in multiple pages or reuse multiple times in a single page (see Figure 7.3). The AddressForm User control is contained in Listing 7.10. From the Library of Wow! eBook ptg 312 CHAPTER 7 Creating Custom Controls with User Controls LISTING 7.10 AddressForm.ascx <%@ Control Language=”C#” ClassName=”AddressForm” %> <script runat=”server”> public string Title { get { return ltlTitle.Text; } set { ltlTitle.Text = value; } } public string Street { get { return txtStreet.Text; } set { txtStreet.Text = value; } } public string City { get { return txtCity.Text; } set { txtCity.Text = value; } } FIGURE 7.3 Displaying multiple address forms with the AddressForm User control. From the Library of Wow! eBook ptg 313 Creating User Controls 7 public string State { get { return txtState.Text; } set { txtState.Text = value; } } public string PostalCode { get { return txtPostalCode.Text; } set { txtPostalCode.Text = value; } } </script> <fieldset> <legend> <asp:Literal ID=”ltlTitle” Text=”Address Form” runat=”server” /> </legend> <div class=”addressLabel”> <asp:Label ID=”lblStreet” Text=”Street:” AssociatedControlID=”txtStreet” Runat=”server” /> </div> <div class=”addressField”> <asp:TextBox ID=”txtStreet” Runat=”server” /> <asp:RequiredFieldValidator ID=”reqStreet” Text=”(required)” ControlToValidate=”txtStreet” Runat=”server” /> </div> <br class=”clear” /> <div class=”addressLabel”> <asp:Label ID=”lblCity” Text=”City:” From the Library of Wow! eBook . top-left drop-down list and selecting the TabClick event from the top-right drop-down list. NOTE The ASP. NET Framework includes a Menu control that you can use to create both tab- strips and pop-up. named PropertyRandomImage, exposes a property named ImageFolderPath. LISTING 7.5 PropertyRandomImage.ascx <%@ Control Language=”C#” ClassName=”PropertyRandomImage” %> <%@ Import Namespace=”System.IO”. control appear in both Intellisense and the Property window. The page in Listing 7.7 demonstrates how you can set the ImageFolderPath programmatically. LISTING 7.7 ShowProgrammatic.aspx <%@ Page