If c1.GetType Is GetTypeWebUserControl Then’This control is not participating in OutputCache CTypec1, WebUserControl.ID = "myWebUserControl1" CTypec1, WebUserControl.Text = "My users con
Trang 1If (c1.GetType() Is GetType(WebUserControl)) Then
’This control is not participating in OutputCache CType(c1, WebUserControl).ID = "myWebUserControl1"
CType(c1, WebUserControl).Text = "My users controls text"
ElseIf (c1.GetType() Is GetType(PartialCachingControl) And _
((CType(c1, PartialCachingControl)).CachedControl IsNot Nothing)) Then
’The control is participating in output cache, but has expired Dim myWebUserControl as WebUserControl = _
CType((CType(c1, PartialCachingControl).CachedControl), _
WebUserControl)
myWebUserControl.ID = "myWebUserControl1"
myWebUserControl.Text = "My users controls text"
End If
End Sub
</script>
C#
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
Control myForm = Page.FindControl("Form1");
Control c1 = LoadControl("WebUserControl.ascx");
myForm.Controls.Add(c1);
if (c1 is WebUserControl)
{
//This control is not participating in OutputCache ((WebUserControl)c1).ID = "myWebUserControl1";
((WebUserControl)c1).Text = "My users controls text";
}
else if ((c1 is PartialCachingControl) &&
((PartialCachingControl)c1).CachedControl != null) {
//The control is participating in output cache, but has expired WebUserControl myWebUserControl =
((WebUserControl)((PartialCachingControl)c1).CachedControl);
myWebUserControl.ID = "myWebUserControl1";
myWebUserControl.Text = "My users controls text";
}
}
</script>
The sample demonstrates how you can test to see what type theLoadControlreturns and set properties based on the type For more information on caching, check out Chapter 23
Finally, in all the previous samples that demonstrate dynamically adding user controls, the user
controls have been added during thePage_Loadevent But there may be times when you want to add
the control based on other events, such as a button’sClickevent or theSelectedIndexChangedevent
of a DropDownList control Using these events to add user controls dynamically presents challenges
Specifically, because the events may not be raised each time a page postback occurs, you need to create a way to track when a user control has been added so that it can be re-added to the Web page as additional
Trang 2A simple way to do this is to use the ASP.NET session to track when the user control is added to the Web
page Listing 26-9 demonstrates this
Listing 26-9: Tracking added user controls across postbacks
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
’Make sure the control has not already been added to the page
If ((Session("WebUserControlAdded") Is Nothing) Or _ (Not CBool(Session("WebUserControlAdded")))) Then
Dim myForm As Control = Page.FindControl("Form1") Dim c1 As Control = LoadControl("WebUserControl.ascx") myForm.Controls.Add(c1)
Session("WebUserControlAdded") = True End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
’Check to see if the control should be added to the page
If ((Session("WebUserControlAdded") IsNot Nothing) And _ (CBool(Session("WebUserControlAdded")))) Then
Dim myForm As Control = Page.FindControl("Form1") Dim c1 As Control = LoadControl("WebUserControl.ascx") myForm.Controls.Add(c1)
End If End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button"
OnClick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="Button" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
Trang 3//Make sure the control has not already been added to the page
if ((Session["WebUserControlAdded"] == null) ||
(!(bool)Session["WebUserControlAdded"])) {
Control myForm = Page.FindControl("Form1");
Control c1 = LoadControl("WebUserControl.ascx");
myForm.Controls.Add(c1);
Session["WebUserControlAdded"] = true;
} }
protected void Page_Load(object sender, EventArgs e)
{
//Check to see if the control should be added to the page
if ((Session["WebUserControlAdded"] != null) &&
((bool)Session["WebUserControlAdded"])) {
Control myForm = Page.FindControl("Form1");
Control c1 = LoadControl("WebUserControl.ascx");
myForm.Controls.Add(c1);
} }
</script>
This sample used a simpleSessionvariable to track whether the user control has been added to the page When the Button1Clickevent fires, the session variable is set toTrue, indicating that the user control
has been added Then, each time the page performs a postback, thePage_Loadevent checks to see if the session variable is set toTrue, and if so, it re-adds the control to the page
Ser ver Controls
The power to create server controls in ASP.NET is one of the greatest tools you can have as an ASP.NET developer Creating your own custom server controls and extending existing controls are actually both
quite easy In ASP.NET 3.5, all controls are derived from two basic classes:System.Web.UI.WebControls WebControlorSystem.Web.UI.ScriptControl Classes derived from theWebControlclass have the
basic functionality required to participate in the Page framework These classes include most of the
common functionality needed to create controls that render a visual HTML representation and provide support for many of the basic styling elements such as Font, Height, and Width Because theWebControl class derives from theControlclass, the controls derived from it have the basic functionality to be a
designable control, meaning they can be added to the Visual Studio Toolbox, dragged onto the page
designer, and have their properties and events displayed in the Property Browser
Controls derived from theScriptControlclass build on the functionality that theWebControlclass
provides by including additional features designed to make working with client-side script libraries
easier The class tests to ensure that a ScriptManager control is present in the hosting page during the
controls’ PreRender stage, and also ensures that derived controls call the the proper ScriptManager
methods during the Render event
1203
Trang 4WebControl Project Setup
This section demonstrates just how easy it is to create custom server controls by creating a very simple
server control that derives from theWebControlclass In order to create a new server control, you create
a new ASP.NET Server Controlproject You can use this project to demonstrate concepts throughout the
rest of this chapter In Visual Studio, choose File ➪ New Project to open the New Project dialog box
From the Project Types tree, open either the Visual Basic or Visual C# nodes and select the Web node
Figure 26-2 shows the New Project dialog with a Visual C# ASP.NET Server Control project template
selected
Figure 26-2
When you click OK in the New Project dialog box, Visual Studio creates a new ASP.NET Server
Con-trol project for you Notice that the project includes a template class that contains a very simple server
control Listing 26-10 shows the code for this template class
Listing 26-10: The Visual Studio ASP.NET Server Control class template
VB
Imports System
Imports System.Collections.Generic
Imports System.ComponentModelImports System.Text
Imports System.Web
Imports System.Web.UI
Trang 5<DefaultProperty("Text"), _
ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")> _
Public Class ServerControl1
Inherits WebControl
<Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> _
Property Text() As String
Get
Dim s As String = CStr(ViewState("Text"))
If s Is Nothing Then
Return "[" + Me.ID + "]"
Else
Return s End If
End Get
Set(ByVal Value As String)
ViewState("Text") = Value
End Set
End Property
Protected Overrides Sub RenderContents(ByVal output As HtmlTextWriter)
output.Write(Text)
End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ServerControl1 : WebControl
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? "[" + this.ID + "]" : s);
}
1205
Trang 6set { ViewState["Text"] = value;
} }
protected override void RenderContents(HtmlTextWriter output) {
output.Write(Text);
} }
}
This template class creates a basic server control that exposes one property calledTextand renders the
value of that property to the screen Notice that you override theRenderContentsmethod of the control
and write the value of theTextproperty to the pages output stream We talk more about rendering
output later in the chapter
Note that creating a server control project is not the only way to create an ASP.NET server control.
Visual Studio 2008 also provides a basic ASP.NET Server Control file template that you can add to
either an existing ASP.NET Server Control project, or to any other standard class library project This
template however differs slightly from the template used to create the default server control included in
the ASP.NET Server control project It uses a different filename scheme, and includes slightly different
code in the default Text propertys getter.
Now, take this class and use it in a sample Web application by adding a new Web Project to the existing
solution The default Web page, created by Visual Studio, serves as a test page for the server control
samples in this chapter
Visual Studio 2008 will automatically add any controls contained in projects in the open Solution to
the Toolbox for you To see this, simply build the Solution and then open the default Web page of the
Web Project you just added The Toolbox should contain a new section called WebControlLibrary1
.Components, and the new server control should be listed in this section (see Figure 26-3)
Now, all you have to do is drag the control onto the Web Form, and the control’s assembly is
automati-cally added to the Web project for you When you drag the control from the Toolbox onto the designer
surface, the control adds itself to the Web page Listing 26-11 shows you what the Web page source code
looks like after you have added the control
Listing 26-11: Adding a Web Control Library to a Web page
<%@ Register Assembly="MyServerControl"
Namespace="ServerControl1" TagPrefix="cc1" %>
<!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 runat="server">
<title>Adding a Custom Web Control</title>
</head>
Trang 7<form id="form1" runat="server">
<div>
<cc1:ServerControl1 ID="ServerControl1" runat="server" />
</div>
</form>
</body>
</html>
Figure 26-3
After you drag the control onto the Web form, take a look at its properties in the Properties Window
Figure 26-4 shows the properties of your custom control
Notice that in addition to theTextproperty you defined in the control, the control has all the basic
properties of a visual control, including various styling and behavior properties The properties are
exposed because the control was derived from theWebControlclass The control also inherits the base
events exposed byWebControl
Make sure the control is working by entering a value for theTextproperty and viewing the page in a
browser Figure 26-5 shows what the page looks like if you set theTextproperty to"Hello World!"
1207
Trang 8Figure 26-4
As expected, the control has rendered the value of theTextproperty to the Web page If you view the
HTML source of this sample, you will see that not only has ASP.NET added the value of the Text property
to the HTML markup, but it has surrounded the text with a<SPAN>block If you look at the code for the
WebControlclass’s render method, you can see why
Trang 9protected internal override void Render(HtmlTextWriter writer)
{
this.RenderBeginTag(writer);
this.RenderContents(writer);
this.RenderEndTag(writer);
}
Figure 26-5 You can see that, by default, theRendermethod, which calls theRenderContentsmethod, also includes theRenderBeginTagandRenderEndTagmethods, causing theSpantags to be added If you have provided
anIDvalue for your control, then theSpantag will also, by default, render anIDattribute Having the
Spantags can sometimes be problematic, so if you want to prevent this in ASP.NET, you simply override theRenderMethodand call theRenderContentsmethod directly
VB
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Me.RenderContents(writer) End Sub
C#
protected override void Render(HtmlTextWriter writer)
{
this.RenderContents(writer);
}
This prevents ASP.NET from automatically adding theSpantags
The samples in this section demonstrate just how easy it is to create a simple server control Of course,
this control does not have much functionality and lacks many of the features of a server control The
following section shows how you can use attributes to enhance this server control to make it more useful and user-friendly
Control Attributes
A key enhancement to the design-time experience for users utilizing server controls is achieved by adding attributes to the class level and to the control’s classes and properties Attributes define much of how
1209
Trang 10the control behaves at design time in Visual Studio For instance, when you look at the default control
template from the previous section (Listing 26-6), notice that attributes have been applied to both the
Classand to theTextproperty In this section, you study these attributes and how they affect the
behav-ior of the control
Class Attributes
Class attributes generally control how the server control behaves in the Visual Studio Toolbox and when
placed on the design surface The class attributes can be divided into three basic categories: attributes
that help the Visual Studio designer know how to render the control at design time, attributes that help
you tell ASP.NET how to render nested controls, and attributes that tell Visual Studio how to display the
control in the Toolbox The following table describes some of these attributes
Designer Indicates the designer class this control should use to render a design-time
view of the control on the Visual Studio design surface TypeConverter Specifies what type to use as a converter for the object
DefaultEvent Indicates the default event created when the user double-clicks the control
on the Visual Studio design surface DefaultProperty Indicates the default property for the control
ControlBuilder Specifies aControlBuilderclass for building a custom control in the
ASP.NET control parser ParseChildren Indicates whether XML elements nested within the server controls tags
will be treated as properties or as child controls TagPrefix Indicates the text the control is prefixed with in the Web page HTML
Property/Event Attributes
Property attributes are used to control a number of different aspects of server controls You can use
attributes to control how your properties and events behave in the Visual Studio Property Browser You
can also use attributes to control how properties and events are serialized at design time The following
table describes some of the property and event attributes you can use
Obviously, the class and property/event attribute tables present a lot of information upfront You already
saw a demonstration of some of these attributes in Listing 26-1; now, as you go through the rest of the
chapter, you will spend time working with most of the attributes listed in the tables
Control Rendering
Now that that you have seen the large number of options you have for working with a server control
at design-time, look at what you need to know to manage how your server control renders its HTML at
runtime