Lesson 3: Creating Rendered Custom Controls

Lesson 3: Creating Rendered Custom Controls

Rendered custom controls are created almost entirely from scratch, which means that you have complete control over how they appear and act. However, because they are not composed of child controls, the way composite controls are, you have to write code to perform the tasks that you could otherwise delegate to child controls.

Composite and rendered controls are closely related, and this lesson extends the skills you developed in Lesson 2. Some of the topics here apply equally to composite and rendered controls you should consider this lesson to be advanced topics for Web custom control development. That said, there s still a lot more that could be taught on the subject. For a comprehensive guide to developing Web custom controls, see Developing ASP.NET Server Controls and Components, by Nikhil Kothari and Vandana Datye (Microsoft Press, 2002).

After this lesson, you will be able to

  • Create a custom control s appearance using the Render method and the HtmlTextWriter utility methods

  • Save and restore property values through the control s ViewState

  • Get text and controls contained between a custom control s begin and end HTML tags

  • Respond to user actions on a control by raising cached or postback events

  • Get data that was entered on the control by the user

  • Add custom controls to the Visual Studio .NET Toolbox

  • Change the Toolbox icon and HTML TagPrefix used for the control by Visual Studio .NET

Estimated lesson time: 40 minutes

Creating and Using Rendered Controls

If you walked through the procedures described in Lesson 2, you ve already created a rendered custom control. The code template that Visual Studio .NET generates when you create a Web Control Library project is, in fact, a rendered control, but it s a simple control that doesn t do much. You can create more interesting controls more quickly using composition, which is why we looked at creating composite controls before creating rendered controls.

Because rendered custom controls are very similar to composite custom controls, the techniques you learned in Lesson 2 apply throughout this lesson as well, with one exception: instead of creating the control s visual interface from other controls, rendered controls create their visual interfaces exclusively from HTML elements. This means that you don t have built-in properties, methods, or events you can use to get or display data; instead, you must create them yourself.

Creating rendered custom controls is similar to creating composite custom controls. To create rendered custom controls, follow these steps:

  1. Create a solution containing a custom control project.

  2. Add a Web application project to the solution, and set it as the startup project. You ll use the Web application project to test the custom control during development.

  3. Add a project reference from the Web application to the custom control project, and then add an HTML @Register directive and control element to use the custom control on a Web form.

  4. Create the custom control s visual interface by overriding the base class s Render method.

  5. Write code to store property values, respond to user actions, and get data from the user as needed.

The following sections describe the last two steps in greater detail. The last two sections in this lesson show how to add completed custom controls to the Toolbox and how to set the icons and generated tags used by Visual Studio .NET for the controls. These last two sections apply equally to composite controls.

Creating the Rendered Control s Appearance

You create a rendered custom control s appearance by overriding the base class s Render method and writing to the method s output argument using the HtmlTextWriter utility methods. The HtmlTextWriter methods summarized in Table 11-3 let you add HTML to the output argument.

Table 11-3. HtmlTextWriter Utility Methods

Method

Description

AddAttribute

Adds an HTML attribute to the next HTML element to be rendered.

RenderBeginTag

Renders the begin tag of an HTML element for later writing by the WriteLine method.

RenderEndTag

Renders the end tag of an HTML element and writes the element and any rendered attributes that are pending. All rendered attributes are cleared after RenderEndTag.

Write

Immediately writes a string.

WriteAttribute

Immediately writes an HTML attribute.

WriteBeginTag

Immediately writes the begin tag of an HTML element.

WriteEndTag

Immediately writes the end tag of an HTML element.

WriteFullBeginTag

Immediately writes the begin tag along with the closing bracket (>) for the HTML element.

WriteLine

Immediately writes a line of content. This is equivalent to the Write method, but WriteLine adds a newline character as well.

As you can probably tell from Table 11-3, there are two approaches to writing HTML elements to the output argument. The most direct approach is to use the Write methods to add the HTML directly to HtmlTextWriter. For example, the following code creates a button that displays a message box when the user clicks it:

Visual Basic .NET

Imports System.ComponentModel Imports System.Web.UI Public Class AlertButton Inherits System.Web.UI.WebControls.WebControl Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Write a title output.Write("<h3>Rendered Control</h3>") ' Opens an Input HTML tag (inserts "<INPUT"). output.WriteBeginTag("INPUT") ' Write some attributes. output.WriteAttribute("value", "Custom Button") output.WriteAttribute("type", "button") output.WriteAttribute("onclick", "javascript:alert('Howdy!')") ' Close the Input HTML tag (inserts ">"). output.WriteEndTag("INPUT") End Sub End Class

Visual C#

using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; namespace csRenderedSnippet { public class AlertButton : System.Web.UI.WebControls.WebControl { protected override void Render(HtmlTextWriter output) { // Write a title output.Write("<h3>Rendered Control</h3>"); // Opens an Input HTML tag (inserts "<INPUT"). output.WriteBeginTag("INPUT"); // Write some attributes. output.WriteAttribute("value", "Custom Button"); output.WriteAttribute("type", "button"); output.WriteAttribute("onclick", "javascript:alert('Howdy!')"); // Close the Input HTML tag (inserts ">"). output.WriteEndTag("INPUT"); } } }

If you add this code to a custom control project, build the control, and then add the resulting custom control to a Web form, at run time the control will appear as shown in Figure 11-14.

figure 11-14 the alertbutton rendered custom control in action

Figure 11-14. The AlertButton rendered custom control in action

As an alternative to writing directly to HtmlTextWriter, you can render tags and attributes and then write them as a unit using the RenderEndTag method. The following code shows the AlertButton custom control Render method written using this alternative approach:

Visual Basic .NET

Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Write a title output.Write("<h3>Rendered Control</h3>") ' Add some attributes. output.AddAttribute("value", "Custom Button") output.AddAttribute("type", "button") output.AddAttribute("onclick", "javascript:alert('Howdy!')") ' Opens an Input HTML tag (inserts "<INPUT"). output.RenderBeginTag("INPUT") ' Close the Input HTML tag (inserts ">"). output.RenderEndTag() End Sub

Visual C#

protected override void Render(HtmlTextWriter output) { // Write a title output.Write("<h3>Rendered Control</h3>"); // Add some attributes. output.AddAttribute("value", "Custom Button"); output.AddAttribute("type", "button"); output.AddAttribute("onclick", "javascript:alert('Howdy!')"); // Opens an Input HTML tag (inserts "<INPUT"). output.RenderBeginTag("INPUT"); // Close the Input HTML tag (inserts ">"). output.RenderEndTag(); }

The advantage of rendering the HTML elements in this way is that you can create the HTML attributes in any sequence.

Storing Property Settings

The composite custom control samples shown in Lesson 2 stored property settings using the properties from their contained controls. Because rendered controls don t have contained controls, you must use the rendered control s ViewState to store any property settings you want to retain between page displays.

The following code shows a Text property that retains its value between page displays:

Visual Basic .NET

Property Text() As String Get ' If the property has been set If Not IsNothing(ViewState("Text")) Then ' Return the settng. Return ViewState("Text") Else ' Otherwise return "". Return "" End If End Get Set(ByVal Value As String) ' Store the property setting. ViewState("Text") = Value End Set End Property

Visual C#

public string Text { get { // If the property has been set if (ViewState["Text"] != null) // Return the settng. return ViewState["Text"].ToString(); else // Otherwise return "". return null; } set { // Store the property setting. ViewState["Text"] = value; } }

Setting ViewState serializes data and stores it in a hidden field on the Web form. When the page is posted back to the server, returning a value from ViewState retrieves and deserializes the data from the hidden field.

ViewState is optimized for String, ArrayList, and HashTable data types, but it can save any data that can be serialized or that provides a TypeConverter. For other types of data, you can create your own code to save and restore ViewState by overriding the SaveViewState and LoadViewState methods.

Getting Contained Text

HTML elements often enclose literal text that they modify in some way, as shown by the following HTML tags used to create boldface text:

<b>Bold me</b>

To get contained text from within a custom control, follow these steps:

  1. Add a ParseChildren attribute to the control s class definition.

  2. Implement the INamingContainer interface in the custom control class.

  3. Retrieve the contained text using the Controls collection.

The following custom control class shows how to retrieve the text between a custom control s begin and end tags to display the contained text in red:

Visual Basic .NET

' ParseChildren attribute enables contained controls. <ParseChildren(False)> Public Class Red Inherits WebControls.WebControl ' This interface makes it possible to get the Controls array. Implements INamingContainer Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Contained text is returned as a Literal control. Dim litText As LiteralControl ' Get the contained text from the Controls collection. litText = Controls(0) ' Make it red using the <font> element. output.Write("<font color='red'>" & litText.Text & "</font>") End Sub End Class

Visual C#

[ParseChildren(false)] public class Red : System.Web.UI.WebControls.WebControl, INamingContainer { // INamingContainer interface makes it possible to get the Controls array. protected override void Render(HtmlTextWriter output) { // Contained text is returned as a Literal control. LiteralControl litText ; // Get the contained text from the Controls collection. litText = (LiteralControl)Controls[0]; // Make it red using the <font> element. output.Write("<font color='red'>" + litText.Text + "</font>"); } }

On a Web form, you would use the preceding custom control through the following HTML:

<custom:red  runat="server">Some red text</custom:red>

You can use the Controls collection to get any items that exist between the custom control s begin and end tags, including other controls. For example, the following custom control class groups contained controls in a panel, centers the controls on the page, and displays them on a red background:

Visual Basic .NET

' ParseChildren attribute enables contained controls. <ParseChildren(False)> Public Class Center Inherits WebControls.WebControl ' This interface makes it possible to get the Controls array. Implements INamingContainer Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Add some attributes for the panel. output.AddAttribute("align", "center") output.AddStyleAttribute("BACKGROUND-COLOR", "red") ' Start a panel output.RenderBeginTag("div") ' Declare a variable to get contained controls. Dim ctrItem As Control ' For each contained control. For Each ctrItem In Controls ' Render the control ctrItem.RenderControl(output) Next output.RenderEndTag() End Sub End Class

Visual C#

[ParseChildren(false)] public class Center : System.Web.UI.WebControls.WebControl, INamingContainer { // INamingContainer interface makes it possible to get the Controls array. protected override void Render(HtmlTextWriter output) { // Add some attributes for the panel. output.AddAttribute("align", "center"); output.AddStyleAttribute("BACKGROUND-COLOR", "red"); // Start a panel output.RenderBeginTag("div"); // For each contained control. foreach (Control ctrItem in Controls) { // Render the control ctrItem.RenderControl(output); } output.RenderEndTag(); } }

Responding to User Actions

Composite custom controls can use their contained controls events to respond to user actions, as shown in Lesson 2. Rendered controls, however, need to take special steps to respond to user actions. How you deal with user actions depends on the type of event:

  • Cached events can be raised from the custom control s code.

  • Postback events must be raised from the client side using a script rendered by the custom control.

The following sections show how to raise each of these types of events.

Raising Cached Events

Cached events are handled by the Web form s server-side code when the Web form is posted back to the server and after the Load and postback events have been handled. Raising a cached event involves two steps:

  1. Declare an event to raise.

  2. Raise the event from somewhere within the custom control s code.

For example, the following custom control class defines an OnChange event that is raised whenever the Text property changes:

Visual Basic .NET

<DefaultEvent("OnChange")>Public Class RenderText Inherits WebControls.WebControl Event Change(ByVal sender As Object, ByVal e As EventArgs) Property Text() As String Get ' If the property has been set If Not IsNothing(ViewState("Text")) Then ' Return the settng. Return ViewState("Text") Else ' Otherwise return "". Return "" End If End Get Set(ByVal Value As String) ' Store the property setting. ViewState("Text") = Value OnChange(EventArgs.Empty) End Set End Property ' Event method. Protected Overridable Sub OnChange(ByVal e As EventArgs) ' Raise event. RaiseEvent Change(Me, EventArgs.Empty) End Sub Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Set the Input control's attributes. output.AddAttribute("value", Me.Text) ' Create an Input control element using above. output.RenderBeginTag("Input") ' Close the Input control element (inserts />). output.RenderEndTag() End Sub End Class

Visual C#

[DefaultEvent("Change")] public class RenderText : System.Web.UI.WebControls.WebControl { // Declare event. public event EventHandler Change; public string Text { get { // If the property has been set if (ViewState["Text"] != null) // Return the settng. return ViewState["Text"].ToString(); else // Otherwise return "". return null; } set { // Store the property setting. ViewState["Text"] = value; // Call event method. OnChange(EventArgs.Empty); } } protected virtual void OnChange(EventArgs e) { if (Change != null) // Raise event. Change(this, e); } protected override void Render(HtmlTextWriter output) { // Set the Input control's attributes. output.AddAttribute("value", this.Text); // Create an Input control element using above. output.RenderBeginTag("Input"); // Close the Input control element (inserts />). output.RenderEndTag(); } }

Notice that the class definition above sets Change as the default event for the control. That means that Visual Studio .NET will generate the event procedure if you double-click the custom control in the Web Forms Designer.

Use the following code to handle the Change event from the Web form:

Visual Basic .NET

Private Sub txtTest_OnChange(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles txtTest.OnChange Response.Write("Text changed!") End Sub

Visual C#

private void txtTest_Change(object sender, System.EventArgs e) { Response.Write("Text changed!"); }

Raising Postback Events

Postback events cause the Web form to be posted back to the server for immediate processing. They are handled immediately after the Web form s Load event. To raise a postback event from a custom control, follow these steps:

  1. Implement the IPostBackEventHandler interface in the custom control.

  2. Declare an event to raise.

  3. Render an HTML element that can respond to client-side events, such as OnClick.

  4. Add an attribute to the HTML element containing a script to post the page back to the server.

  5. Raise the event from the RaisePostBackEvent method, which is part of the IPostBackEventHandler interface.

The following code shows how to use these steps to raise the Click postback event from a custom control:

Visual Basic .NET

' Raises PostBack event. <DefaultEvent("Click")> Public Class AlertButton Inherits System.Web.UI.WebControls.WebControl ' (1) Interface that allows PostBack event processing. Implements IPostBackEventHandler ' (2) Declare postback event Event Click(ByVal sender As Object, ByVal e As EventArgs) ' (3) Render an HTML element that can detect user events. Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Add some attributes. output.AddAttribute("value", "Postback Button") output.AddAttribute("type", "button") ' (4) Add attribute to raise Postback event on client. output.AddAttribute("onclick", "javascript:alert('Howdy!');" & _ Page.GetPostBackEventReference(Me)) ' Opens an Input HTML tag (inserts "<INPUT"). output.RenderBeginTag("INPUT") ' Close the Input HTML tag (inserts ">" and writes attributes). output.RenderEndTag() End Sub ' Part of the IPostBackEventHandler interface. ' you must create this method. Public Sub RaisePostBackEvent(ByVal eventArgument As String) _ Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent ' (5) Raise the event. OnClick(EventArgs.Empty) End Sub Protected Overridable Sub OnClick(ByVal e As EventArgs) ' Raise the event. RaiseEvent Click(Me, EventArgs.Empty) End Sub End Class

Visual C#

// (1) IPostBackEventHandler interface allows PostBack event processing. [DefaultEvent("Click")] public class AlertButtonThree : System.Web.UI.WebControls.WebControl, IPostBackEventHandler { // (2) Declare postback event public event EventHandler Click; // (3) Render an HTML element that can detect user events. protected override void Render(HtmlTextWriter output) { // Write a title output.Write("<h3>Rendered Control</h3>"); // Add some attributes. output.AddAttribute("value", "Custom Button"); output.AddAttribute("type", "button"); // (4) Add attribute to raise Postback event on client. output.AddAttribute("onclick", "javascript:alert('Howdy!');" + Page.GetPostBackEventReference(this)); // Opens an Input HTML tag (inserts "<INPUT"). output.RenderBeginTag("INPUT"); // Close the Input HTML tag (inserts ">"). output.RenderEndTag(); } // Part of the IPostBackEventHandler interface. // you must create this method. public void RaisePostBackEvent(string eventArgument) { // (5) Call the event method to raise event. OnClick(EventArgs.Empty); } protected virtual void OnClick(EventArgs e) { // Raise the event. if (Click != null) Click(this, e); } }

When the user clicks the preceding custom control at run time, the button s OnClick event runs the following script:

alert('Howdy!'); //Displays a message box. __doPostBack('winTest',''); //Generated by Page.GetPostBackEventReference(Me);

The __doPostBack method posts the page back to the server, where it is intercepted by the IPostBackEventHandler interface s RaisePostBackEvent method, which in turn raises the Click event from within the control.

Use the following code to handle the Click event from the Web form:

Visual Basic .NET

Private Sub altTest_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles altTest.Click Response.Write("Button clicked!") End Sub

Visual C#

private void altTest(object sender, System.EventArgs e) { Response.Write("Button clicked!"); }

Getting Data from the User

Rendered controls don t automatically retain the data entered by the user. You can see this if you create a TextBox custom control by rendering an HTML Input element: you can type in the Input element, but as soon as the page is posted back to the server, whatever you typed is gone.

To get data from the user, follow these steps:

  1. Implement the IPostBackDataHandler interface.

  2. Add a name attribute to uniquely identify the HTML element to get data from.

  3. Override the LoadPostBackData method from the IPostBackDataHandler interface. Use this method to get the data from the user.

  4. Override the RaisePostDataChangedEvent method from the IPostBackData Handler interface. You don t have to write code for this method, but you must override it because it is part of the interface.

  5. Raise an event to indicate that the data has changed. This step is optional if you don t want to provide a change event for the control, you don t have to.

The following custom control shows how to use these steps to retain data entered by a user in a custom TextBox control rendered from an HTML Input element:

Visual Basic .NET

<DefaultEvent("Change")> Public Class RenderText Inherits WebControls.WebControl ' (1) Interface that allows you to get PostBack data. Implements IPostBackDataHandler Event Change(ByVal sender As Object, ByVal e As EventArgs) Property Text() As String Get ' If the property has been set If Not IsNothing(ViewState("Text")) Then ' Return the settng. Return ViewState("Text") Else ' Otherwise return "". Return "" End If End Get Set(ByVal Value As String) ' Store the property setting. ViewState("Text") = Value ' Call event method. OnChange(EventArgs.Empty) End Set End Property Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) ' Set the Input control's attributes. output.AddAttribute("value", Me.Text) ' (2) You must define this attribute to enable PostBack data. output.AddAttribute("name", Me.UniqueID) ' Create an Input control element using above. output.RenderBeginTag("Input") ' Close the Input control element. output.RenderEndTag() ' Write the element to the HtmlTextWriter. output.WriteLine() End Sub ' (3) Get data from the user. ' You must create this method. Public Function LoadPostData(ByVal postDataKey As String, _ ByVal postCollection As _ System.Collections.Specialized.NameValueCollection) As Boolean _ Implements System.Web.UI.IPostBackDataHandler.LoadPostData ' If the user changes Input value, update the text property. If Me.Text <> postCollection(postDataKey) Then Me.Text = postCollection(postDataKey) ' Returning True invokes RaisePostDataChangedEvent below. Return True Else ' Returning False does not invoke RaisePostDataChangedEvent. Return False End If End Function ' (4) Override RaisePostDataChangedEvent method. ' You must create this method. Public Sub RaisePostDataChangedEvent() Implements _ System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent ' (5) Call the event method. This is optional. OnChange(EventArgs.Empty) End Sub ' Event method. Protected Overridable Sub OnChange(ByVal e As EventArgs) ' Raise event RaiseEvent Change(Me, EventArgs.Empty) End Sub End Class

Visual C#

// (1) IPostBackDataHandler interface allows you to get PostBack data. [DefaultProperty("Text"), DefaultEvent("Change")] public class RenderText : System.Web.UI.WebControls.WebControl, IPostBackDataHandler { // Declare event. public event EventHandler Change; [DefaultValue("")] public string Text { get { // If the property has been set if (ViewState["Text"] != null) // Return the settng. return ViewState["Text"].ToString(); else // Otherwise return "". return null; } set { // Store the property setting. ViewState["Text"] = value; // Call event method. OnChange(EventArgs.Empty); } } protected override void Render(HtmlTextWriter output) { // Set the Input control's attributes. output.AddAttribute("value", this.Text); // (2) You must define this attribute to enable PostBack data. output.AddAttribute("name", this.UniqueID); // Create an Input control element using above. output.RenderBeginTag("Input"); // Close the Input control element (inserts />). output.RenderEndTag(); } // (3) Get data from the user. // You must create this method. public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { // If the user changes Input value, update the text property. if (this.Text != postCollection[postDataKey]) { this.Text = postCollection[postDataKey]; // Returning true invokes RaisePostDataChangedEvent. return true; } else // Returning False does not invoke RaisePostDataChangedEvent. return false; } // (4) Override RaisePostDataChangedEvent method. // You must create this method. public void RaisePostDataChangedEvent() { // (5) Call the event method. This is optional. OnChange(EventArgs.Empty); } protected virtual void OnChange(EventArgs e) { if (Change != null) // Raise event. Change(this, e); } }

Adding Custom Controls to the Toolbox

After you ve created and debugged a set of custom controls, you can add them to the Visual Studio .NET Toolbox by following these steps:

  1. Choose Customize Toolbox from the Tools menu. Visual Studio .NET displays the Customize Toolbox dialog box, as shown in Figure 11-15.

    figure 11-15 adding items to the toolbox

    Figure 11-15. Adding items to the Toolbox

  2. Click the .NET Framework Components tab, and then click Browse. Visual Studio .NET displays the Open dialog box.

  3. Use the Open dialog box to locate and select the assembly (.dll) containing the custom controls to add to the Toolbox, and then click Open. Visual Studio .NET opens the assembly and adds the contained controls to the list of controls in the Customize Toolbox dialog box.

  4. Click OK to close the Customize Toolbox dialog box.

After you ve added custom controls to the Toolbox, they appear under the General category when Visual Studio .NET is in Design mode, as shown in Figure 11-16.

figure 11-16 custom controls in the toolbox

Figure 11-16. Custom controls in the Toolbox

To add a custom control to a Web form, simply double-click the control or drag the control from the Toolbox to the Web form. When you add a custom control from the Toolbox, Visual Studio .NET automatically adds the @Register directive for the control to the Web form and inserts the HTML for the custom control, as shown in boldface in the following HTML:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="CustomControl.aspx.vb" Inherits=" MCSDWebAppsVB.CustomControl"%> <%@ Register TagPrefix="Custom" Namespace="RenderedControls"  Assembly="RenderedControls" %><HTML> <body> <form  method="post" runat="server"> <Custom:Chart  runat="server"></cc1:Chart> </form> </body> </HTML>

The icons that appear for the custom control in the Toolbox and the TagPrefix used in the HTML for the control can be changed using attributes in the custom control s assembly, as described in the following section.

Setting the Toolbox Icon and TagPrefix for Custom Controls

You can customize your controls to display unique icons in the Toolbox and use their own TagPrefix attributes in HTML. If you ve already added the custom controls to your Toolbox, you must unload them and then add them back to the Toolbox before any of these changes take effect.

To add a Toolbox icon to a custom control, follow these steps:

  1. Create a 16-by-16 bitmap file containing the icon to display in the Toolbox.

  2. Name the bitmap file using the same base name as the class name for the custom control it represents. For example, Red.bmp is the icon for the custom control with the class name Red.

  3. Set the bitmap file s Build Action property to Embedded Resource in Solution Explorer.

  4. Rebuild the control.

To change the TagPrefix used by a custom control in HTML, follow these steps:

  1. Add the following lines to the custom control project s AssemblyInfo file:

    Visual Basic .NET

    Imports System.Web.UI <Assembly: TagPrefix("project.namespace", "prefix")>

    Visual C#

    using System.Web.UI [assembly: TagPrefix("namespace", "prefix")]

  2. Rebuild the project.

In the preceding procedure, project.namespace is the project name and namespace for the custom control, and prefix is the prefix to use for the custom controls from that namespace.



MCAD(s)MCSD Self-Paced Training Kit(c) Developing Web Applications With Microsoft Visual Basic. Net and Microsoft V[.  .. ]0-315
MCAD(s)MCSD Self-Paced Training Kit(c) Developing Web Applications With Microsoft Visual Basic. Net and Microsoft V[. .. ]0-315
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 118

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