Creating a Compiled Control

  1. Open Visual Studio .NET and create a new ASP.NET Web Application named TCWeb.
  2. Right-click on the solution in Solution Explorer, point to Add, then click New Project.

  1. In the New Project dialog box, select the Web Control Library template and set the name to MyControlLib, and then click OK.
  2. Visual Studio will automatically create a class named WebCustomControl1 for you. Delete the WebCustomControl1.cs file.
  3. Right-click on the MyControlLib project in Solution Explorer, point to Add, then click Add New Item.
  4. In the Add New Item dialog, select the Web Custom Control template and set its name to MyTable.
  5. If it is not already open, double-click on the MyTable.cs file to edit the code.

 

  1. As you can Visual Studio created a skeleton class for you. Delete the Text property code in the MyTable class by removing the following code:

 

private string text;

 

[Bindable(true),

      Category("Appearance"),

      DefaultValue("")]

public string Text

{

      get

      {

            return text;

      }

 

      set

      {

            text = value;

      }

}

 

  1. Next we will implement the INamingContainer interface in our control class. You do this by typing in “, INamingContainer following the  class declaration. As you can see in the following class declaration below, we are declaring a class named MyTable that inherits from the WebControl base class. Plus we are implementing the interface INamingContainer. This interface is simply a marker container that .NET uses so that when our control gets rendered, any child controls we create will inherit the control’s identification.

 

public class MyTable : System.Web.UI.WebControls.WebControl, INamingContainer

 

For more information about inheritance and interfaces, see

 

 

  1. At the top of the class, add the following “using” statement:

 

using System.Web.UI.HtmlControls;

 

  1. In the Render event code (protected override void Render) delete the line of code that says “output.Write(Text);” and replace it with the following line of code:

 

RenderContents(output);

 

  1. RenderContents is a method that allows us to use the .NET control object model to programmatically create HTML elements such as HtmlTables, LinkButtons, etc. For more information see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemWebUIWebControlsWebControlClassRenderContentsTopic.asp

 

  1. Next we will override the CreateChildControls method

 

        protected override void CreateChildControls()

        {

            Controls.Clear();

            CreateControlHierarchy();

     }

 

  1. Because our CreateChildControls method calls the function CreateControlHierarchy(), we will need to write that function. Write the following code to implement that function. What this function will do is create an HTML table with 10 rows with that each have 2 cells. The first cell will contain a number (such as a ID that could be represented by a database value. The second will contain a LinkButton control (that renders as an HTML anchor tag). We will wire up the click event later.

 

        private void CreateControlHierarchy()

        {

            HtmlTable table = new HtmlTable();

            table.Border = 1;

            table.Width = "100%";

            for(int i = 0; i < 10; i++)

            {

                HtmlTableRow row = new HtmlTableRow();

                HtmlTableCell numberCell = new HtmlTableCell();

                numberCell.InnerHtml = i.ToString();

                row.Cells.Add(numberCell);

                HtmlTableCell buttonContainerCell = new HtmlTableCell();

                LinkButton button = new LinkButton();

                button.CommandArgument = i.ToString();

                button.Text = "Button " + i.ToString();

                //button.Click += new EventHandler(button_Click);

                buttonContainerCell.Controls.Add(button);

                row.Cells.Add(buttonContainerCell);

                table.Rows.Add(row);

            }

            this.Controls.Add(table);

       }


 

  1. Add a new class file to the MyControlLib project named MyTableEventArgs.

 

  1. The MyTableEventArgs class will inherit from the .NET EventArgs class. This way when someone clicks on one of the 10 LinkButtons that will get rendered in our table, we can intelligently provide them with the number associated with the item. Again, this could just as easily be an ID from a database table. The code for the MyTableEventArgs class should look like the following:

 

using System;

namespace MyControlLib

{

      public class MyTableEventArgs : System.EventArgs

      {

        private int _id;

        public MyTableEventArgs() {}

           

        public int ID

        {

            get {return _id;}

            set {_id = value;}

        }

      }

}

For more information about the .NET EventArgs class, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemeventargsclasstopic.asp

 

  1. Save the MyTableEventArgs.cs file and then re-open the MyTable.cs file.
  2. Add the following declarations to the MyTable control class

 

public delegate void MyTableClickHandler(object sender, MyTableEventArgs e);

public event MyTableClickHandler MyTableClick;

 

The first line of code above is a delegate declaration. A delegate is similar to a function pointer in C. Think of it as an object that has the ability to reference a method of another object that contains the same function signature. For more information about delegates, see:

 

The second line of code declares an event named MyTableClick. The MyTableClick event will have the same signature defined by the MyTableClickHandler delegate. That means that the subscriber to the event (client) can create a function with two parameters: object and MyTableEventArgs to handle the event. For more information about events and how they relate to delegates, see:

·       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkEventsTutorial.asp

·       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconEventsOverview.asp

 

  1. Next, go into the CreateControlHeirarchy function and uncomment the following line of code:

 

button.Click += new EventHandler(button_Click);

 

This line of code basically says, “For this button control’s click Event, set the event handler function to be “button_click”. This is the function we will write in the next step.


 

 

  1. As stated in the previous step, we need to write the function that handles the button click event.

 

  private void button_Click(object sender, EventArgs e)

  {

    if(null != MyTableClick)

    {

        LinkButton lb = sender as LinkButton;

        MyTableEventArgs args = new MyTableEventArgs();

        args.ID = Int32.Parse(lb.CommandArgument);

        this.MyTableClick(this, args);

    }

}

 

This code first checks to see if there are any subscribers to the MyTableClick event by checking to make sure it is not null. If you try to raise the event when there are no subscribers you will get a nice little exception thrown. I hate that design in C# and I have formally taken issue with the C# team about that because it breaks abstraction from an object-oriented design perspective, but that’s just my $.02.

 

The next thing that happens in this event is that we convert the sender object to a LinkButton using the “as” keyword. The “as” keyword in C# works with reference types and basically says “convert this generic object to a LinkButton object.” If the sender object was not of type LinkButton, the result would be null. But we can safely assume at this point that the object will be a LinkButton.

 

Next, we create a new instance of our custom EventArgs class. We will then assign the CommandArgument property of the LinkButton control (that we set in step #14) to the ID property of our custom EventArg object.

 

The last line of code simply raises the event to our subscribers passing a reference to our control as the “sender object” and our custom EventArgs object “MyTableEventArgs.”

 

  1. That’s it! Compile your control and in the next set of steps will write an ASP.NET page that will use the control.

 


Using Your Custom Control on a Web Form

  1. In the TCWeb project you created in the previous exercise, right-click on the References folder icon in Solution Explorer and then click Add Reference.

 

 

  1. In the Add reference dialog, click on the Projects tab, then double click on the MyControlLib project and click OK to add the reference to our control library project.


  1. Open WebForm1.aspx in HTML view and at the top of the page, add the following Register tag.

 

<%@ Register TagPrefix="cc1" Namespace="MyControlLib" Assembly="MyControlLib" %>

 

This will register our control library on the page so we can use any controls the library contains: namely the MyTable control we created in the last exercise.

 

  1. In between the form element in HTML view, add the following markup tags:

 

<p>POSTBACK MESSAGE:

<asp:Label id="Label1" runat="server"></asp:Label></p>

<br>

<br>

<cc1:MyTable id="myTableControl" runat="server"></cc1:MyTable>

 

This adds a Label control and an instance of our custom control on the page.

 

  1. The HTML view or your ASPX page should now look similar to the following:

 

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="TCWeb.WebForm1" %>

<%@ Register TagPrefix="cc1" Namespace="MyControlLib" Assembly="MyControlLib" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

 

<html>

  <head>

    <title>WebForm1</title>

    <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">

    <meta name="CODE_LANGUAGE" Content="C#">

    <meta name=vs_defaultClientScript content="JavaScript">

    <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">

  </head>

  <body MS_POSITIONING="GridLayout">

    <form id="Form1" method="post" runat="server">

        <p>POSTBACK MESSAGE:

        <asp:Label id="Label1" runat="server"></asp:Label></p>

        <br>

        <br>

        <cc1:MyTable id="myTableControl" runat="server"></cc1:MyTable>

    </form>

  </body>

</html>

 

  1. Now, switch from HTML view to Design view and save your page.

 


  1. In Solution Explorer, right-click on WebForm1.aspx and then click View Code.

 

This will take you into the code-behind for the page. As you can see there is already some C# code in there for you.

 

  1. Now you will wire up the MyTableClick event to a function in your page’s code-behind. To do this, type the following line of code in the Page_Load function:

 

NOTE: as you are typing this code, you will be prompted to have the function written for you automatically which is a cool IDE feature the C# team gave to us. When you see the following hit the Tab button your keyboard twice to have the function written for you automatically (if you miss it, don’t worry).

 

myTableControl.MyTableClick += new

        MyControlLib.MyTable.MyTableClickHandler(myTableControl_MyTableClick);

 

 

  1. The code for your Page_Load and myTableControl_MyTableClick event procedures should look similar to the following: (if not, type it in or copy/paste)

 

private void Page_Load(object sender, System.EventArgs e)

{

    myTableControl.MyTableClick += new

        MyControlLib.MyTable.MyTableClickHandler(myTableControl_MyTableClick);

}

 

private void myTableControl_MyTableClick(object sender, MyControlLib.MyTableEventArgs e)

{

 

}

 

  1. Now, type the following code in the myTableControl_MyTableClick function

 

this.Label1.Text = "Button ID pressed was: " + e.ID.ToString();

 

What this will do is display a message in our label control showing the ID property of our custom EventArgs class that we created in the previous exercise.

 

  1. Save your code and press F5 to run the application:
  2. When you run the application, your custom control should display showing an HTML table containing the numbers 0 through 9 and associated link buttons. Note that when you click on any of the link buttons, the label button displays which one you click as illustrated below.

 

 

 

 

  1. That’s it! You have now developed a custom Web control that exposes events to clients. Remember that controls are UI elements. You should NEVER query any databases or do ANY kind of business logic within controls. Controls are meant to be UI elements only, so if you need to perform business logic based on an action that occurs for a control, raise an event as we did in this exercise and have the code-behind for the Web page call the business logic.

 

Additionally, if you need to provide the control with data, create a DataSource property and pass it whatever you what to use (DataSet, XML, ArrayList, etc). From within the control you can use the associated data source, such as a DataSet to display data to the user. Also don’t forget that you have the option of creating Web User controls (ASCX files), which are a simpler way to create controls. The difference being that a compiled control is more advanced and can be used in several projects. Whereas it is much quicker and easier to develop a Web user control because they have an HTML view and are similar to developing a regular ASPX page.

 

For more information, see the following:

 

·       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbconwebusercontrolsvscustomwebcontrols.asp