User Controls


User controls provide Web developers with a quick way to repeat the same little section of a Web Form on multiple Web Forms. You can create a user control once and then deploy it to as many Web Forms as you like. Something in the user control that gets changed immediately shows up in all Web Forms that use the user control. No longer do you have to wade through multiple Web Forms to make the same correction to all of them.

Here are five things that you need to know about user controls:

  1. User controls are basically the same thing as a Web Form, except they don't have an <HTML>, <BODY>, or <FORM> tag. This is because a Web Form is only allowed one copy of each of these, and the main Web Form where you inserted the user control will already have them. It also has a @ Control directive instead of a @ Page directive, though the contents of the directive other than the directive name would be, in most cases, the same.

  2. A user control has the suffix .ascx, which enables the compiler to differentiate between a Web Form and a user control. Also, it stops the compiler from generating an error for the missing aforementioned tags.

  3. By convention, a user control codebehind has the suffix .ascx.h, though truthfully you can use just about anything.

  4. The codebehind class is virtually the same as a Web Form's except that it is abstract and inherits from System::Web::UI::UserControl.

  5. A user control can't execute on its own. It has to be inserted into a Web Form to run. Personally, I like to lay out the Web Form using a table tag or Table control and then insert the appropriate user control into each table cell. This isn't required, though. You can use a user control just like any HTML or intrinsic control. Therefore, you can place a user control however you like on a Web Form.

Other than that, there isn't much to user controls.

Creating a User Control

Probably one of the most common user controls you will come across when developing Web Forms is the Header user control. Virtually every page on a Web site will have a header. It only makes sense that you create a control to display it, if only for the reason that if you need to change your header, you will only need to do it once with a user control.

Header.ascx (see Listing 14-19) and Header.ascx.h (see Listing 14-20) are the GUI design and codebehind for the simple Header user control found on my Web site http://www.contentmgr.com. You might recognize the code if you read my book, Real World ASP.NET: Building a Content Management System.

Listing 14-19: The ASP.NET GUI Design File Header.ascx

start example
 <%@ Assembly Name="WebForms" %> <%@ Control Inherits="WebForms.uc.Header" %> <asp:Image id=imgHeader runat="server"></asp:Image> <BR> <HR width="100%" SIZE="1"> 
end example

Listing 14-20: The Codebehind Header.ascx.h

start example
 using namespace System; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     namespace uc     {         public __gc __abstract class Header : public UserControl         {         private:             String *level;         protected:             WebControls::Image *imgHeader;             void OnLoad(EventArgs *e)             {                 // Set the image based on passed header level                 imgHeader->ImageUrl =                     String::Concat(S"Images/", level, S".jpg");                 UserControl::OnLoad(e);             }         public:             // Create property to pass header level             __property String *get_Level()             {                 return level;             }             __property void set_Level(String *level)             {                 this->level = level;             }         };     } } 
end example

Not much to it, is there? The only thing you need to note is the GUI design code for the user control can't contain any <HTML>, <BODY>, or <FORM> tags, and you use the @ Control directive and not the @ Page directive. Other than that, user controls and Web Form GUI design code are exactly the same.

Not much different from a Web Form, is it? First, I added another level to the namespace hierarchy, just to remind me that this is a user control. This is completely optional, but it helps me understand better where I am in the code.

The second and probably most important thing to notice is that the user control class inherits from System::Web::UI::UserControl and not System::Web::UI::Page. Because of this, you also have to call the UserControl::OnLoad() method and not the Page::OnLoad() method.

If you are observant, you may have noticed that you did not define the header's image URL within the design code. The reason is that you want to be able to change it based on which page it is currently heading. This dynamic functionality needs to be added to the codebehind.

The solution is elegant and very simple. Make anything you want passed to the user control a property. Then, if the user control is implemented statically within the GUI design file, pass the information as an attribute in the user control tag, or in the codebehind set the value using the property. On the other hand, if the user control is implemented dynamically, your only option is setting the property within the codebehind. You will see both of these methods later in the chapter. The code within the user control's codebehind to handle passed values is standard property logic.

Statically Implementing a User Control

As you can see in Listing 14-21, the static implementation of a user control is done entirely within the GUI design file. No changes are needed in the codebehind.

Listing 14-21: The ASP.NET GUI Design File Blank.aspx Implementing a User Control

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.Blank" %> <%@ Register TagPrefix="myUC" TagName="Header" src="/books/2/474/1/html/2/Header.ascx" %> <HTML>   <HEAD>     <title>Blank</title>   </HEAD>   <body>     <form  method="post" runat="server">       <myUC:Header  Level="Home" runat="server"></myUC:Header>     </form>   </body> </HTML> 
end example

The first step in implementing a user control is to register it with the @ Register directive.

TagPrefix is used to ensure that the user control tag is unique and can be anything you want, so long as it abides by standard C++ variable-naming rules. For example, it is possible that you may have two user controls that have the exact same name, especially if you use third-party user controls. So, by prefixing these identically named user controls with different TagPrefixes, you will make the user control names unique.

TagName is an alias to associate the user control with its class. It should match the name you gave the user control when you created it.

Src is the name of the user control's GUI design filename. Src may also include a path. Unfortunately, it must be relative to the root directory of the Web application and can't be a URI.

 <%@ Register TagPrefix="myUC" TagName="Header" src="/books/2/474/1/html/2/Header.ascx" %> 

The second (and last) step is to place the user control within the form tag of your Web Form. Optionally, as I show in the example, you can pass a value to the user control using an attribute. The name of the attribute must match exactly the name of the property that you placed within your user control's codebehind.

 <myUC:Header  Level="Home" runat="server"></myUC:Header> 

What if you don't know the name of the image you want to place in the header at design time? Or what if you need to calculate it based on some set of values? To solve these problems, you need to set the Image property of the user control within the Web Form's codebehind.

Listing 14-22 shows how to call the user control without any user control-specific attributes. Notice that the only difference is that the Level attribute is not specified.

Listing 14-22: The ASP.NET GUI DESIGN FILE Blank2.aspx Implementing a User Control

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.Blank2" %> <%@ Register TagPrefix="myUC" TagName="Header" src="/books/2/474/1/html/2/Header.ascx" %> <HTML>   <HEAD>     <title>Blank</title>   </HEAD>   <body>     <form  method="post" runat="server">       <myUC:Header  runat="server"></myUC:Header>     </form>   </body> </HTML> 
end example

Listing 14-23 shows how to update the attributes within the codebehind.

Listing 14-23: The Codebehind Blank2.aspx.h

start example
 using namespace System; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class Blank2 : public Page     {     protected:         WebForms::uc::Header *pgHeader;         void OnLoad(EventArgs *e)         {             // set image to home in user control             pgHeader->Level = S"Home";         }     }; } 
end example

As you can see, the code is hardly rocket science. The only thing worth noting is that you use a definition to the user control within this class. Therefore, you need to define the user control before you define this class. In other words, make sure you place user controls before Web Forms in the linker file.

Figure 14-16 shows the user control header at the top of a blank page.

click to expand
Figure 14-16: The user control header

Dynamically Implementing a User Control

The process of creating user controls dynamically is not difficult. It is just not obvious how it needs to be done. You would think that you could simply create a new user class with the new operator and you are done:

 Header *header = new Header();  // Invalid code 

If you were to compile the preceding code, you would get an error. Remember, I said earlier that a user control's codebehind class is abstract. Abstract classes can't be instantiated directly. In other words, you can use the new operator with them.

So how do you create a user control? The answer is, you don't. Instead, you load the user control using the Page class's LoadControl() method. The basic syntax of the LoadControl() method is as follows:

 Control* LoadControl(String *virtualPathToControl); 

Because the LoadControl() method returns a control, you need to typecast it to the specific user control type you are loading. Notice that I also stated that it takes a virtual path as a parameter. This means that it can take only paths with a root of the Web application. This means that a URI to the user control's .ascx file is not allowed:

 Header *header = dynamic_cast<Header*>(LoadControl("Header.ascx")); 

ManyHeadings.aspx (see Listing 14-24) and ManyHeadings.aspx.h (see Listing 14-25) are the GUI design and codebehind showing how to dynamically create user controls. This Web Form simply places two headers at the top of an otherwise empty Web Form.

Listing 14-24: The ASP.NET GUI Design File ManyHeadings.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.ManyHeadings" %> <HTML>   <HEAD>     <title>ManyHeadings</title>   </HEAD>   <body>     <form  method="post" runat="server">       <asp:Table  runat="server" Width="100%">         <asp:TableRow>           <asp:TableCell ></asp:TableCell>           <asp:TableCell ></asp:TableCell>         </asp:TableRow>       </asp:Table>     </form>   </body> </HTML> 
end example

Listing 14-25: The Codebehind ManyHeadings.aspx.h

start example
 using namespace System; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; using namespace WebForms::uc; namespace WebForms {     public __gc class ManyHeadings : public Page     {     protected:         TableCell *cell00;         TableCell *cell01;         void OnLoad(EventArgs *e)         {             Header *header;             header = dynamic_cast<Header*>(LoadControl("Header.ascx"));             header->Level = S"Home";             cell00->Controls->Add(header);             header = dynamic_cast<Header*>(LoadControl("Header.ascx"));             header->Level = S"Domain";             cell01->Controls->Add(header);         }     }; } 
end example

As you can see, there is no trace of the user controls in the GUI design file. However, I did create two cells to simplify the coding in the codebehind. Normally, you would probably create the cells programmatically within the code-behind as you saw earlier in the chapter.

Now that you know how to load user controls, the preceding code shows how easy it is to create them dynamically.

Figure 14-17 shows two dynamically created user control headers at the top of a blank page.

click to expand
Figure 14-17: Two dynamic user control headers




Managed C++ and. NET Development
Managed C++ and .NET Development: Visual Studio .NET 2003 Edition
ISBN: 1590590333
EAN: 2147483647
Year: 2005
Pages: 169

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