Evjen c20.tex V2 - 01/28/2008 3:13pm Page 958 Chapter 20: ASP.NET AJAX Control Toolkit Dim dt As New DataTable dt.Load(myReader) myReader.Close() Dim myGrid As New GridView myGrid.ID = "GridView1" myGrid.DataSource = dt myGrid.DataBind() Dim sw As New StringWriter Dim htw As HtmlTextWriter = New HtmlTextWriter(sw) myGrid.RenderControl(htw) htw.Close() Return sw.ToString() End Function End Class C# using System.Data; using System.Data.SqlClient; using System.IO; using System.Web.UI; using System.Web.UI.WebControls; public partial class DynamicPopulateExtender : System.Web.UI.Page { [System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()] public static string GetDynamicContent(string contextKey) { SqlConnection conn; SqlCommand cmd; string cmdString = "Select * from Customers"; switch (contextKey) { case ("1"): cmdString = "Select * from Employees"; break; case ("2"): cmdString = "Select * from Products"; break; } conn = new SqlConnection(@"Data Source=. \ SQLEXPRESS; AttachDbFilename=|DataDirectory| \ NORTHWND.MDF; Integrated Security=True;User Instance=True"); // Put this string on one line in your code cmd = new SqlCommand(cmdString, conn); conn.Open(); 958 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 959 Chapter 20: ASP.NET AJAX Control Toolkit SqlDataReader myReader; myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); DataTable dt = new DataTable(); dt.Load(myReader); myReader.Close(); GridView myGrid = new GridView(); myGrid.ID = "GridView1"; myGrid.DataSource = dt; myGrid.DataBind(); StringWriter sw = new StringWriter(); HtmlTextWriter htw = new HtmlTextWriter(sw); myGrid.RenderControl(htw); htw.Close(); return sw.ToString(); } } This code is the code-behind page for the DynamicPopulateExtender.aspx page and contains a single method that is callable asynchronously. The GetDynamicContent() method takes a single parameter, contextKey , a string value that can be used to determine what link the end user clicked. Based upon the selection, a specific command string is used to populate a DataTable object. From here, the DataTable object is used as the data source for a programmatic GridView control that is rendered and returned as a string to the client. The client will take the large string and use the text to populate the Panel1 control that is on the page. The result of clicking one of the links is shown in Figure 20-21. FilteredTextBoxExtender The FilteredTextBoxExtender control works off a TextBox control to specify the types of characters the end user can input into the control. For instance, if you want the end user to be able to enter only numbers into the text box, then you can associate a FilteredTextBoxExtender to the TextBox control and specify such behavior. An example of this is presented in Listing 20-16. Listing 20-16: Filtering a text box to use only numbers < %@ Page Language="C#" % > < %@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" % > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > FilteredTextBoxExtender Control < /title > < /head > Continued 959 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 960 Chapter 20: ASP.NET AJAX Control Toolkit < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < cc1:FilteredTextBoxExtender ID="FilteredTextBoxExtender1" runat="server" TargetControlID="TextBox1" FilterType="Numbers" > < /cc1:FilteredTextBoxExtender > < asp:TextBox ID="TextBox1" runat="server" >< /asp:TextBox > < /div > < /form > < /body > < /html > Figure 20-21 In this case, a FilteredTextBoxExtender control is attached to the TextBox1 control through the use of the TargetControlID property. The FilteredTextBoxExtender control has a property called FilterType that has the possible values of Custom , LowercaseLetters , Numbers ,and UppercaseLetters . This example uses a FilterType value of Numbers , meaning that only numbers can be entered into the text box. If the end user tries to enter any other type of information, t hen nothing happens — it will seem to the end user as if the key doesn’t even function. 960 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 961 Chapter 20: ASP.NET AJAX Control Toolkit Another property the FilteredTextBoxExtender control exposes is the FilterMode and the InvalidChars properties. An example of using these two properties is presented here: < cc1:FilteredTextBoxExtender ID="FilteredTextBoxExtender1" runat="server" TargetControlID="TextBox1" InvalidChars="*" FilterMode="InvalidChars" > < /cc1:FilteredTextBoxExtender > The default value of the FilterMode property is ValidChars .Whensetto ValidChars , t he control works from the FilterType property and only allows what this property defines. When set to InvalidChars , you then use the InvalidChars property and put the characters here (multiple characters all go together with no space or item between them). HoverMenuExtender The HoverMenuExtender control allows you to make a hidden control appear on the screen when the end user hovers on another control. This means that you can build either elaborate ToolTips or provide extra functionality when an end user hovers somewhere in your application. One example is to change a ListView control so that when the end user hovers over a product name, the Edit button for that row of data appears on t he screen. The code for the < ItemTemplate > in the ListView control is partially shown in Listing 20-17. Listing 20-17: Adding a hover button to the ListView control’s ItemTemplate < ItemTemplate > < tr style="background-color:#DCDCDC;color: #000000;" > < td > < cc1:HoverMenuExtender ID="HoverMenuExtender1" runat="server" TargetControlID="ProductNameLabel" PopupControlID="Panel1" PopDelay="25" OffsetX="-50" > < /cc1:HoverMenuExtender > < asp:Panel ID="Panel1" runat="server" Height="50px" Width="125px" > < asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="Edit" / > < /asp:Panel > < /td > < td > < asp:Label ID="ProductIDLabel" runat="server" Text=’ < %# Eval("ProductID") % > ’/ > < /td > < td > < asp:Label ID="ProductNameLabel" runat="server" Text=’ < %# Eval("ProductName") % > ’/ > < /td > < ! Code removed for clarity > < /tr > < /ItemTemplate > 961 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 962 Chapter 20: ASP.NET AJAX Control Toolkit Here, a HoverMenuExtender control is attached to the Label control with the ID of ProductNameLabel , which appears in each row of the ListView control. This is done using the TargetControlID property, while the PopupControlID property is used to assign the control that appears dynamically when a user hovers the mouse over the targeted control. The HoverMenuExtender control exposes several properties that control the style and behaviors of the popup. First off, the PopDelay property is used in this example and provides a means to delay the popup from occurring (in milliseconds). The OffsetX and OffsetY properties specify the location of the popup based upon the targeted control. In this case, the offset is set to -50 (pixels). The results of the operation are shown in Figure 20-22. Figure 20-22 ListSearchExtender The ListSearchExtender control extends either a ListBox or a DropDownList control, though not always with the best results in browsers such as Opera and Safari. This extender allows you to provide search capabilities through large collections that are located in either of these controls. This alleviates the need for the end users to search through the collection to find the item they are looking for. When utilized, the extender adds a search text that shows the characters the end user types for their search area above the control. Listing 20-18 shows the use of this extender. 962 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 963 Chapter 20: ASP.NET AJAX Control Toolkit Listing 20-18: Extending a ListBox control with the ListSearchExtender control < %@ Page Language="C#" % > < %@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" % > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > ListSearchExtender Control < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < cc1:ListSearchExtender ID="ListSearchExtender1" runat="server" TargetControlID="ListBox1" > < /cc1:ListSearchExtender > < asp:ListBox ID="ListBox1" runat="server" Width="150" > < asp:ListItem > Aardvark < /asp:ListItem > < asp:ListItem > Bee < /asp:ListItem > < asp:ListItem > Camel < /asp:ListItem > < asp:ListItem > Dog < /asp:ListItem > < asp:ListItem > Elephant < /asp:ListItem > < /asp:ListBox > < /div > < /form > < /body > < /html > In this case, the only property used in the ListSearchExtender control is the TargetControlID property to associate which control it extends. Running this page produces the results shown in Figure 20-23. Figure 20-23 Then, as an end user, when you start typing, you will see what you are typing in the text above the control (as shown in Figure 20-24). Figure 20-24 963 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 964 Chapter 20: ASP.NET AJAX Control Toolkit You can customize the text that appears at the top of the control with the PromptCssClass , PromptPosi- tion ,and PromptText properties. By default, the PromptPosition is set to Top (the other possible value is Bottom )andthe PromptText value is Type to search . MaskedEditExtender and MaskedEditValidator The MaskedEditExtender control is similar to the FilteredTextBoxExtender control in that it restricts the end user from entering specific text within a TextBox control. This control takes the process one step further in that it provides the end user a template within the text box for them to follow. If the end users do not follow the template, they will be unable to proceed and might get a validation warning from the control using the MaskedEditValidator control. Listing 20-19 provides an example of using both of these controls. Listing 20-19: Using both the MaskedEditExtender and the MaskedEditValidator controls < %@ Page Language="C#" % > < %@ Register Assembly="AjaxControlToolkit, Version=3.5.11119.20050, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" Namespace="AjaxControlToolkit" TagPrefix="cc1" % > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > MaskedEditExtender Control < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < cc1:MaskedEditExtender ID="MaskedEditExtender1" runat="server" TargetControlID="TextBox1" MaskType="Number" Mask="999" > < /cc1:MaskedEditExtender > < asp:TextBox ID="TextBox1" runat="server" >< /asp:TextBox > < cc1:MaskedEditValidator ID="MaskedEditValidator1" runat="server" ControlExtender="MaskedEditExtender1" ControlToValidate="TextBox1" IsValidEmpty="False" EmptyValueMessage="A three digit number is required!" Display="Dynamic" >< /cc1:MaskedEditValidator > < /div > < /form > < /body > < /html > In this case, the MaskedEditExtender control uses the TargetControlID to associate itself with the TextBox1 control. The MaskType property supplies the type of mask or filter to place on the text box. The possible values include: ❑ None –means that no validation will be performed. ❑ Date – means date validation will occur. 964 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 965 Chapter 20: ASP.NET AJAX Control Toolkit ❑ DateTime –means date and time validation will occur. ❑ Number –means a number validation will occur. ❑ Time –means a time validation will occur Listing 20-19 uses Number and then specifies the mask or template the numbers need to take. This is done through the use of the Mask property. In this case, the Mask property is set to 999 . This means that all numbers can be only three digits in length. Using 999 as a value to the Mask property means that when end user enters a value in the text box, he will be presented with three underscores inside the text box. This is the template for entering items. This is shown in Figure 20-25. Figure 20-25 If the Mask property is changed to 99,999.99 as follows: < cc1:MaskedEditExtender ID="MaskedEditExtender1" runat="server" TargetControlID="TextBox1" MaskType="Number" Mask="99,999.99" > < /cc1:MaskedEditExtender > the textbox template appears as illustrated in Figure 20-26. Figure 20-26 From Figure 20.26, you can see that the comma and the period are present in the template. As the end users type, they do not need to retype these values. The cursor will simply move to the next section of numbers required. As you can see from the Mask property value, numbers are represented by the number 9 . When working with other MaskType values, you also need to be aware of the other mask characters. These are provided here in the following list: ❑ 9— Only a numeric character ❑ L— Only a letter ❑ $— Only a letter or a space ❑ C— Only a custom character (case sensitive) ❑ A— Only a letter or a custom character ❑ N— Only a numeric or custom character ❑ ?— Any character 965 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 966 Chapter 20: ASP.NET AJAX Control Toolkit In addition to the character specifications, the delimiters used in the template are detailed in the following list: ❑ / is a date separator ❑ : is a time separator ❑ . is a decimal separator ❑ , is a t housand separator ❑ \ is the escape character ❑ { is the initial delimiter for repetition of masks ❑ } is the final delimiter for repetition of masks Using some of these items, you can easily change MaskedEditExtender to deal with a DateTime value: < cc1:MaskedEditExtender ID="MaskedEditExtender1" runat="server" TargetControlID="TextBox1" MaskType="DateTime" Mask="99/99/9999 99:99:99" > < /cc1:MaskedEditExtender > The template created in the text box for this is shown in Figure 20-27. Figure 20-27 The MaskedEditExtender control has a ton of properties that are exposed to control and manipulate the behavior and style of the text box. The MaskedEditExtender control can work in conjunction with the MaskedEditValidator control, which provides validation against the text box controls. In the earlier example, the validation was accomplished through an instance of the MaskedEditValidator control. < cc1:MaskedEditValidator ID="MaskedEditValidator1" runat="server" ControlExtender="MaskedEditExtender1" ControlToValidate="TextBox1" IsValidEmpty="False" EmptyValueMessage="A three digit number is required!" Display="Dynamic" >< /cc1:MaskedEditValidator > This control uses the ControlExtender property to associate itself with the MaskedEditExtender con- trol and uses the ControlToValidate property to watch a specific control on the form. By default, the IsValidEmpty property is set to True , but changing it to False means that the end user will be required to enter some value in the text box in order to pass validation and not get t he error message that is presented in the EmptyValueMessage property. Triggering the MaskedEditValidator control gives you something like the message shown in Figure 20-28. It is important to remember that you can style the control in many ways to produce the validation message appearance that you are looking for. Figure 20-28 966 Evjen c20.tex V2 - 01/28/2008 3:13pm Page 967 Chapter 20: ASP.NET AJAX Control Toolkit MutuallyExclusiveCheckBoxExtender Often you want to offer a list of check boxes that behave as if they are radio buttons. That is, when you have a collection of check boxes, you will only want the end user to make a single selection from the provided list of items. However, unlike a radio button, you also want to enable the end user to deselect an item or to make no selection whatsoever. Using the MutuallyExclusiveCheckBoxExtender control, you can perform such an action. Listing 20-20 shows you how to accomplish this task. Listing 20-20: Using the MutuallyExclusiveCheckBoxExtender control with check boxes < %@ Page Language="C#" % > < %@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" % > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > MutuallyExclusiveCheckBoxExtender Control < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:ScriptManager ID="ScriptManager1" runat="server" > < /asp:ScriptManager > < cc1:MutuallyExclusiveCheckBoxExtender ID="MutuallyExclusiveCheckBoxExtender1" runat="server" TargetControlID="CheckBox1" Key="MyCheckboxes" / > < asp:CheckBox ID="CheckBox1" runat="server" Text="Blue" / >< br / > < cc1:MutuallyExclusiveCheckBoxExtender ID="MutuallyExclusiveCheckBoxExtender2" runat="server" TargetControlID="CheckBox2" Key="MyCheckboxes" / > < asp:CheckBox ID="CheckBox2" runat="server" Text="Brown" / >< br / > < cc1:MutuallyExclusiveCheckBoxExtender ID="MutuallyExclusiveCheckBoxExtender3" runat="server" TargetControlID="CheckBox3" Key="MyCheckboxes" / > < asp:CheckBox ID="CheckBox3" runat="server" Text="Green" / >< br / > < cc1:MutuallyExclusiveCheckBoxExtender ID="MutuallyExclusiveCheckBoxExtender4" runat="server" TargetControlID="CheckBox4" Key="MyCheckboxes" / > < asp:CheckBox ID="CheckBox4" runat="server" Text="Orange" / >< br / > < /div > < /form > < /body > < /html > It is impossible to associate a MutuallyExclusiveCheckBoxExtender control with a CheckBoxList control, therefore, each of the check boxes needs to be laid out with CheckBox controls as the previous code demonstrates. You need to have one MutuallyExclusiveCheckBoxExtender control for each CheckBox control on the page. 967 . Instance=True"); // Put this string on one line in your code cmd = new SqlCommand(cmdString, conn); conn.Open(); 958 Evjen c20.tex V2 - 01/28/2008 3: 13pm Page 959 Chapter 20: ASP. NET AJAX Control Toolkit SqlDataReader. - 01/28/2008 3: 13pm Page 9 63 Chapter 20: ASP. NET AJAX Control Toolkit Listing 20-18: Extending a ListBox control with the ListSearchExtender control < %@ Page Language=" ;C#& quot; % > < %@. character 9 65 Evjen c20.tex V2 - 01/28/2008 3: 13pm Page 966 Chapter 20: ASP. NET AJAX Control Toolkit In addition to the character specifications, the delimiters used in the template are detailed in the following