Chapter 11: The Enhanced Page Framework and Cool New Controls


In the earlier chapters you learned about some new features that will make your life as a developer much easier. Normally, however, you'll only discover many changes if you delve into the details. This chapter summarizes a couple of innovations that you probably haven't heard of yet or that I've just mentioned briefly in this book. A great deal of this chapter is devoted to new controls and the Page class.

Any New Controls Not Mentioned Yet?

Yep, there are some! As I mentioned in Chapter 1, there are more than 40 new controls in the new version of ASP.NET. I've already introduced most of them to you in the previous chapters—for example, the new Data Controls, the Security Controls, and the 11 controls used in the context of Web Parts. But there's more to discover. Let's go!

BulletedList

This control's name tells you what it's about—it renders a bulleted list. To do so, the common HTML tags (for example, <ul> and <li>) are used. In the easiest case, you assign the desired list items statically, as you already know from other data-bound controls such as DropDownList, ListBox, and so on:

 <asp:bulletedlist  runat="server">     <asp:listitem>First value</asp:listitem>     <asp:listitem>Second value</asp:listitem>     <asp:listitem>Third value</asp:listitem> </asp:bulletedlist> 

Many properties influence the design of the control. You can choose between different bullet characters or define your own image. It's also possible to create a numbered list and define its starting value:

 <asp:bulletedlist  runat="server"     bulletstyle="Numbered" firstbulletnumber="15">     <asp:listitem>First value</asp:listitem>     <asp:listitem>Second value</asp:listitem>     <asp:listitem>Third value</asp:listitem> </asp:bulletedlist> 

The BulletedList control is a Data Control, so old and new concepts for data binding are fully supported. The following example shows the application of the control in combination with an XmlDataSource control that gets its content from the XML file books.xml:

 <script runat="server"> void BulletedList3_Click(object sender,     System.Web.UI.WebControls.BulletedListEventArgs e) {     ListItem item = this.BulletedList3.Items[e.Index];     this.LB_SelectedBook.Text = string.Format("You selected '{0}'", item.Text); } </script> ... <asp:bulletedlist  runat="server"     datasource     datatextfield="InnerText"     bulletimageurl="arrow.gif"     bulletstyle="CustomImage"     displaymode="LinkButton"     onclick="BulletedList3_Click" /> <asp:xmldatasource      runat="server" datafile="Books.xml"     xpath="bookstore/genre/book/title"> </asp:xmldatasource> <br /> <asp:label  runat="server"> </asp:label> 

In this example, the control displays the entries as LinkButton controls. If the user clicks one of the buttons, a central event is raised. In this case, the chosen book title is written to a Label control. Figure 11-1 shows the output of all three examples.

click to expand
Figure 11-1: The new BulletedList control is very versatile.

DynamicImage

I've loved this new control since the day Scott Guthrie presented it at TechEd Europe. In the end it's not a big feature, but it's fun to dynamically create and deliver pictures this way. Naturally, this was already possible with earlier versions of ASP.NET. Up until now, however, you had to additionally create and register a separate handler. With version 2.0 this functionality comes right out of the box.

In the next sections, I discuss the practical uses of this control.

Scaling Existing Images

A simple and practical application is to use the DynamicImage control to adapt the size of a picture that already exists on your hard disk. To do so, you must pass the filename to the ImageFile property and assign the desired size of the output with Width and/or Height. The picture will be scaled dynamically and is sent to the browser in the desired format (the standard being JPEG).

 <asp:dynamicimage  runat="server"     imagefile="paramount.gif"     width="150px"> </asp:dynamicimage> 

The picture shown in Figure 11-2 is delivered with a width of 150 pixels. The original one has a width of almost 300 pixels.

click to expand
Figure 11-2: The DynamicImage control allows you to scale existing images.

In this context, the URL of the picture that was referenced in the browser is of interest. It refers to a special handler, CachedImageServiceHandler, of the System.Web.UI.Imaging namespace, to which an ID is passed. Internally, the picture is saved in the Cache of the HttpContext class in conjunction with the unique ID:

 CachedImageService.axd?data=9a9a0768-a0ef-42d0-a895-3e87e41b5622 

A nice example for an application is the generation of a thumbnail list. For this purpose, you can use the control with a data-bound DataList. The example in Listing 11-1 reads the names of all pictures out of the current directory and binds them to the DataList. Figure 11-3 shows the result.

click to expand
Figure 11-3: Creating a thumbnail list is fun now.

Listing 11-1: A Thumbnail List

start example
 <%@ page language="C#" %> <%@ import namespace="System.IO" %> <script runat="server"> void Page_Load(object sender, System.EventArgs e) {     DirectoryInfo directory = new         DirectoryInfo(Path.GetDirectoryName(this.Request.PhysicalPath));     this.DL_Thumbnails.DataSource = directory.GetFiles("*.gif");     this.DL_Thumbnails.DataBind(); } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         <asp:datalist runat="server"  repeatcolumns="2">             <itemtemplate>                 <asp:dynamicimage runat="server"                     imagefile='<%# Eval("Name") %>'                     width="150px">                 </asp:dynamicimage>             </itemtemplate>         </asp:datalist>     </form> </body> </html> 
end example

Passing Dynamically Created Images

You can use the DynamicImage control to display dynamically generated images. The example in Listing 11-2 shows the creation of a little smiley face with the help of the GDI+ classes from the System.Drawing namespace, and Figure 11-4 shows the result.

click to expand
Figure 11-4: Say cheese!

Listing 11-2: "Don't Worry, Be Happy!" (Thanks to the GDI+ Smiley Face)

start example
 <%@ page language="C#" %> <%@ import namespace="System.Drawing" %> <script runat="server"> void Page_Load(object sender, System.EventArgs e) {     this.DI_Image.Image = this.CreateImage(); } private Bitmap CreateImage() {     Bitmap b = new Bitmap(200, 200);     Graphics g = Graphics.FromImage(b);     g.Clear(Color.White);     Pen pen = new Pen(Color.Red);     pen.Width = 3;     g.DrawEllipse(pen, 2, 2, 196, 196);     Point[] points = {new Point(40, 140), new Point(100, 170),         new Point(160, 140)};     g.DrawCurve(pen, points);     g.DrawLine(pen, 100, 70, 100, 130);     Brush brush = new SolidBrush(Color.Black);     g.FillEllipse(brush, 50, 60, 20, 20);     g.FillEllipse(brush, 130, 60, 20, 20);     g.Flush();     return b; } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         This picture was created dynamically:<br /><br />         <asp:dynamicimage  runat="server" imagetype="Gif"/>     </form> </body> </html> 
end example

In this example, the created picture is assigned to the DynamicImage.Image property. Alternatively, you might deliver a byte array to ImageBytes. This is particularly useful if you read the data out of a database, for example. Please be aware that you may only use one of the following properties: ImageBytes, Image, or ImageFile.

Tip

You'll find another example for a similar application of the DynamicImage control in Chapter 10. In that chapter, a DynamicImage control is used for the output of a page counter.

Using an Image Generator Service

One more field of application of the control is the implementation of an Image Generator. This is a new file type with the extension .asix. The source code file contains a class that inherits from the abstract base ImageGenerator and acts as an HttpHandler. Within the abstract method RenderImage(), you can draw your image with the help of GDI+ into an instance of the Graphics class, which is passed as parameter.

Listing 11-3, which has the filename circlegenerator.asix, is based on source code from the official documentation. It draws a couple of randomized ellipses into the passed Graphics object.

Listing 11-3: The Image Generator Outputs a Couple Ellipses

start example
 <%@ Image  Language="C#" %> using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Web.UI.Imaging; public class CircleGenerator : ImageGenerator {     protected override void RenderImage(Graphics g)     {         int width = (int)Style.Width.Value;         int height = (int)Style.Height.Value;         int w = Math.Max(DefaultWidth, width);         int h = Math.Max(DefaultHeight, height);         g.FillRectangle(Brushes.White, g.ClipBounds);         int numberOfCircles = 1;         if (Parameters["NumberOfCircles"] != null)         {             numberOfCircles = Int32.Parse(                 Parameters["NumberOfCircles"].ToString());         }         g.SmoothingMode = SmoothingMode.AntiAlias;         Random random = new Random();         for (int i = 0; i < numberOfCircles; i++)         {             int x = random.Next(w);             int y = random.Next(h);             int circleWidth = random.Next(w/2);             int circleHeight = random.Next(h/2);             int penWidth = random.Next(5);         Color c = Color.FromArgb(random.Next(255), random.Next(255),                                  random.Next(255));         g.DrawEllipse(new Pen(c,penWidth),x,y,circleWidth,circleHeight);         }     } } 
end example

You reference the newly created Image Generator by using the ImageGeneratorUrl property of the DynamicImage class, as shown in Listing 11-4. The ability to pass values has been implemented in a very clever way. ParameterCollection, which you already know from the DataSource controls, serves as the basis. It can get its data from completely different sources, such as cookies, sessions, query strings, and controls. The number of ellipses to be generated is managed by ControlParameter, which queries the value from a TextBox control. Figure 11-5 shows the generated ellipses.

click to expand
Figure 11-5: Custom Image Generators can use parameters.

Listing 11-4: Using an Image Generator with the DynamicImage Control

start example
 <%@ page language="C#"%> <html>     <body>         <form  runat="server">             <table>                 <tr>                     <td valign="top">                         Number of circles:<br />                         <asp:textbox  runat="server" text="15" />                         <br />                         <asp:button  runat="server"                             text="Create Image" />                     </td>                     <td>                         <asp:dynamicimage  runat="server"                             dynamicimagetype="ImageGenerator"                             imagegeneratorurl="CircleGenerator.asix"                             alternatetext="Generated image of circles."                             height="400px" width="300px">                             <parameters>                                 <asp:controlparameter                                     name="NumberOfCircles"                                     propertyname="Text"                                     control>                                 </asp:controlparameter>                             </parameters>                         </asp:dynamicimage>                     </td>                 </tr>             </table>         </form>     </body> </html> 
end example

ImageMap

A second new control from the field of graphics is called ImageMap. You can use this control to provide a picture with clickable hot spots that either act as regular links or initiate a postback. At present, you can define hot spots as circles, rectangles, or polygons. You can implement further types of hot spots if necessary by deriving from the synonymous abstract base class.

In Listing 11-5, the archway of the Paramount Studios is displayed in the browser. Various elements of the picture have been provided with hot spots. Clicking one of these hot spots will result in a postback and then display the description of the clicked zone through a Label control. Figure 11-6 shows the result.

click to expand
Figure 11-6: Welcome to Hollywood!

Listing 11-5: Defining Hot Spots with the ImageMap Control

start example
 <%@ page language="C#" %> <script runat="server"> void ImageMap1_Click(object sender,     System.Web.UI.WebControls.ImageMapEventArgs e) {     this.LB_Message.Text = string.Format("You clicked the {0}.", e.Value); } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         <asp:imagemap  runat="server"             imageurl="paramount.gif"             onclick="ImageMap1_Click"             hotspots-count="5"             hotspotmode="PostBack">             <asp:rectanglehotspot top="43" right="189"                 bottom="141" left="101" value="gate">             </asp:rectanglehotspot>             <asp:polygonhotspot coordinates="18,149,106,122,192,155,98,190"                 value="fountain">             </asp:polygonhotspot>             <asp:circlehotspot radius="30" x="273" y="92" value="tree">             </asp:circlehotspot>             <asp:rectanglehotspot right="295" bottom="145" left="190"                 value="right building">             </asp:rectanglehotspot>             <asp:rectanglehotspot top="52" right="94" bottom="130"                 value="left building">             </asp:rectanglehotspot>         </asp:imagemap>         <br />         <asp:label  runat="server" font-size="20pt">         </asp:label>     </form> </body> </html> 
end example

MultiView and View

In previous versions of ASP.NET, the Panel control was used quite often to switch different views of a single page—for example, for an entry form and the acknowledgement message if it has been handled successfully. Therefore, one panel was deactivated and the other one activated.

In cases like this, .NET version 2.0 offers two controls: MultiView and View. View can be compared with Panel, but it doesn't offer formatting. MultiView is the container for several View elements, and it takes care that only one of them is shown at a time. View controls are directly defined within the MultiView control and are placed visually there. The support in the development environment, however, isn't ideal yet. You can define the View control to be shown initially through the ActiveViewIndex property and you can change the View control programmatically with the ActiveViewIndex property's help or by means of the SetActiveView() method. Listing 11-6 demonstrates this with a simple input form including a confirmation message, and Figure 11-7 shows the result.

click to expand
Figure 11-7: You can use the MultiView and View controls to switch the interface.

Listing 11-6: Switching Views of a Page with the MultiView and View Controls

start example
 <%@ page language="C#" %> <script runat="server"> void Button1_Click(object sender, System.EventArgs e) {     this.LB_Name.Text = this.TB_Name.Text;     this.MultiView1.ActiveViewIndex = 1; } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         <asp:multiview  runat="server" activeviewindex="0">             <asp:view  runat="server">                 Please enter your name:                 <br />                 <br />                 <asp:textbox  runat="server">                 </asp:textbox>                 <asp:button  runat="server" text="OK"                     onclick="Button1_Click" />             </asp:view>             <asp:view  runat="server">                 Your name is                 <asp:label  runat="server">Label</asp:label>             </asp:view>         </asp:multiview>&nbsp;     </form> </body> </html> 
end example

If desired, you can leave it up to the control to choose the active view independently on basis of a query string variable. To do so, you must define the name of the variable through the QueryStringParam property and deliver the ID of the view to be shown in the query string.

Note

The MultiView and View controls are ideal to use in combination with mobile devices. The two controls replace the MobileForm control, which was used in versions 1.0 and 1.1. Generally, usage of the Wizard control I describe in the next section is recommended for "regular" web sites.

Wizard

In many scenarios for regular web sites, usage of the Wizard control may be preferred over the combination of MultiView and View controls. The Wizard control offers the possibility to automatically switch between views out of the box. Even the design support within the VS .NET environment is much better because the control fully integrates itself into the template concepts.

Listing 11-7 basically corresponds to Listing 11-6 for MultiView and View. In the first step of the Wizard control, the user's name has to be specified, and in the second step, the entered text will be displayed again.

Listing 11-7: Creating a Dialog Assistant Page with the Wizard Control

start example
 <%@ page language="C#" %> <script runat="server"> void Wizard1_ActiveViewChanged(object sender, System.EventArgs e) {     this.LB_Name.Text = this.TB_Name.Text; } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         <asp:wizard  runat="server"             sidebarenabled="True"             headertext="My Simple Wizard"             activestepindex="0"             width="100%"             onactiveviewchanged="Wizard1_ActiveViewChanged">             <headerstyle forecolor="White" backcolor="Blue"                 font-names="Verdana" font-size="15pt"                 font-bold="True">             </headerstyle>             <wizardsteps>                 <asp:wizardstep runat="server" title="Step 1">                     Hello!<br />                     <br />                     Please enter your name:                     <asp:textbox runat="server" >                     </asp:textbox>                     <br />                 </asp:wizardstep>                 <asp:wizardstep runat="server" title="Step 2">                     Thanks,<br />                     <br />                     your name is                     <asp:label runat="server" >                     </asp:label>                 </asp:wizardstep>             </wizardsteps>         </asp:wizard>     </form> </body> </html> 
end example

The possibilities of this control are far reaching. You can, for example, create the single steps through a Collection Editor and specify which task should be executed in each single step in a differentiated way—for example, Start, Step, or Finish. If you leave the value Auto unchanged, the control will define the sequence by itself.

As you can see in Figure 11-8, the control doesn't only show the current step but also takes cares of the headline and the buttons to move forward or backward. Furthermore, if you like you can display a SideBar, which allows the user to directly access each step through a link. All elements can either be taken over as default and adapted through styles or formatted individually with templates. In any case, events such as ActiveViewChanged, FinishButtonClicked, NextButtonClicked, PreviousButtonClicked, and SideBarButtonClicked enable you to interfere with the flow of the control.

click to expand
Figure 11-8: The new Wizard control allows you to create easy-to-use wizard steps.

Caution

The only disadvantage with the Wizard control at present involves switching between single steps when you're working with VS .NET. At present, you have to temporarily change the ActiveStepIndex property if you want to work another view at a time. Hopefully this will change in the Beta version.

Panel

The Panel control has been around for quite a while, and you surely have taken advantage of it now and then. In the future, it may become even more useful to you, because the new version of ASP.NET supports scrollbars (horizontally aligned, vertically aligned, or aligned in both directions).

Listing 11-8 shows the application of scrollbars. You must assign a size to the Panel control and activate scrolling. As you can see in Figure 11-9, the control takes care of the rest. Internally a HTML <div> tag with corresponding style sheets is used.

click to expand
Figure 11-9: The Panel control now supports scrolling.

Listing 11-8: Scrolling with the Enhanced Panel Control

start example
 <%@ page language="C#" %> <script runat="server"> void Page_Load(object sender, System.EventArgs e) {     StringBuilder sb = new StringBuilder();     for (int i = 0; i < 100; i++)     {         sb.AppendLine("Hello World<br/>");     }     this.Panel1.Controls.Add(new LiteralControl(sb.ToString())); } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         <asp:panel  runat="server"             width="300px" height="200px" scrollbars="Vertical">         </asp:panel>     </form> </body> </html> 
end example

Pager

Similar to the MultiView and View controls described previously, the Pager control is mainly used for mobile devices. I therefore describe it in detail in Chapter 12. You can use the Pager control to display (page by page) content placed in a control—for example, in the previously explained Panel control. Listing 11-9 shows the control's use.

Listing 11-9: Paging Content with the Pager Control

start example
 <%@ page language="C#" %> <script runat="server"> void Page_Load(object sender, System.EventArgs e) {     for (int i = 0; i < 100; i++)     {         this.Panel1.Controls.Add(             new LiteralControl(string.Format("Hello world ({0})<br/>", i + 1)));     } } </script> <html>   <head>   </head>   <body>     <form  runat="server">       <h3>Pager Class Example</h3>         <asp:pager              controltopaginate="Panel1"             runat="server" itemsperpage="10">         </asp:pager>         <asp:panel  runat="Server" />     </form>   </body> </html> 
end example

In Listing 11-9, 100 instances of the class LiteralControl are added to a Panel control dynamically. The Pager control is used to display the subcontrols in blocks of ten elements each. This is possible because the Panel control supports the IPaginationInfo and IPaginationContainer interfaces. Beside the Panel control, the Pager control can also apply to Web Parts that inherit from the Panel control. Furthermore, the Page and HtmlForm classes support the interfaces.

The primary field of application of the Pager control, in my opinion, is in mobile devices. There you need to show a lot of content on a small display. The Pager's display can be adapted in detail to fulfill this purpose. But, of course, you could also use the control in "regular" web sites; for example, you could use it to list thumbnails on a page, as shown in Figure 11-10.

click to expand
Figure 11-10: You can page content in multiple controls with the new Pager control.

FileUpload

With ASP.NET, uploading files has never been a problem. The corresponding control, however, was only available as a server-side HTML control. With the new version of ASP.NET, the ASP.NET team gives developers a "real" FileUpload web control, as shown in Listing 11-10 and Figure 11-11.

click to expand
Figure 11-11: File upload is now controllable through the Web.

Listing 11-10: Uploading Files Is Now Supported by a "Real" Web Control

start example
 <%@ page language="C#" %> <script runat="server"> void BT_Upload_Click(object sender, System.EventArgs e) {     if ((this.FU_Upload.PostedFile != null) &&         (this.FU_Upload.PostedFile.ContentLength > 0))     {         this.LB_Message.Text = "Thanks!";     }     else     {         this.LB_Message.Text = "No file or empty file!";     } } </script> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server">         <asp:fileupload  runat="server" />         <asp:button  runat="server"                 text="Upload" onclick="BT_Upload_Click" />         <br />         <br />         <asp:label  runat="server">         </asp:label>     </form> </body> </html> 
end example

Tip

The new FileUpload control has one important advantage: It automatically takes care of the correct setting of the enctype (encoding) attribute provided by the server-side <form> tag. This means no more annoying errors because of forgotten appendixes!

HiddenField

The new HiddenField control does exactly what you would expect: It allows the use of a hidden field in the HTML source code of the page. This control is particularly helpful if you create it dynamically. Listing 11-11 shows the use of the HiddenField control.

Listing 11-11: The HiddenField Control

start example
 <asp:hiddenfield          runat="server"     value="Testvalue" /> 
end example

Substitution

Internally, the new Substitution control is used in conjunction with output caching to allow dynamic content even with cached data. Perhaps the Beta version will include some practical "real world" example for its application too.

The only property assigned to this control is the name of a method. This method must correspond with a certain delegate (HttpResponseSubstitutionCallback) and it must be implemented statically within the local Page class. The method receives the current Context object as parameter and will be accessed within the Render() method of the control. This way, the returned string is printed out exactly at the position at which the control has been placed on the page. Listing 11-12 and Figure 11-12 show the use of this control.

click to expand
Figure 11-12: The Substitution control calls the assigned method just in time.

Listing 11-12: Using the PlaceHolder to Output Text

start example
 <%@ page language="C#" %> <script runat="server"> private static string MySubstitutionCallback(HttpContext context) {     return "Hello World"; } </script> <html> <head  runat="server">     <title>Untitled Page</title> </head> <body>     <form  runat="server">         Some text goes here.         <br />         <br />         <asp:substitution  runat="server"             methodname="MySubstitutionCallback"         />         <br />         <br />         Some other text goes here.     </form> </body> </html> 
end example

TextBox

The TextBox control is not new, of course. You know it already and you've surely used it many times. There is a small, but very nice, improvement for the input field. You can now use the AutoCompleteType property to define which VCard entry is used to automatically fill in the field. Internally, the vcard_name HTML attribute is used. If you don't want to use this feature, you can switch it off for the whole form. To do so, you must switch the AutoComplete property (see Listing 11-13) of the server-side form to "off."

Listing 11-13: The TextBox Control with Autocompletion Fields

start example
 <%@ page language="C#" %> <html> <head runat="server">     <title>Untitled Page</title> </head> <body>     <form runat="server" autocomplete="on">         Email:             <asp:textbox  runat="server" autocompletetype="Email" />     </form> </body> </html> 
end example

Control State

You already know about View State from previous versions of ASP.NET. What's new in this version is Control State. Here, I'm talking about data storage that's kept persistent in a hidden form field within the page:

 <input type="hidden" name="__VIEWSTATE" value=" -- lots of data goes here -- " /> <input type="hidden" name="__CONTROLSTATE"     value="/wEXAwUSRGV0YWlsc1ZpZXcxJF9jdGwwEGQC/////w9mBQlHcml     kVmlldzEUKgAGZGRkZmRkBQ9HcmlkVmlldzEkX2N0bDAQZAL/////D2Ysgb     9McYV7cT0rIct23v91bs97qw==" /> 

The new Control State stores data of imminent importance for the control's use. If you deactivated the View State in version 1.0 or 1.x, you could use the former DataGrid control, for example, in a very limited way. This is no longer a problem with the new Control State, because very important information is stored in any case within Control State, while View State takes "only" less important information. What data is stored in what state system varies from control to control.

You can use Control State in your own controls, of course. For that purpose, you must register it first while you handle the OnInit event:

 this.Page.RegisterRequiresControlState(this) 

In addition, you must overwrite the LoadControlState and SaveControlState methods to store and retrieve the desired data.




ASP. NET 2.0 Revealed
ASP.NET 2.0 Revealed
ISBN: 1590593375
EAN: 2147483647
Year: 2005
Pages: 133

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net