
private string
text;
[Bindable(true),
Category("Appearance"),
DefaultValue("")]
public string
Text
{
get
{
return
text;
}
set
{
text = value;
}
}
public class MyTable : System.Web.UI.WebControls.WebControl,
INamingContainer
For more information about inheritance and interfaces, see
using System.Web.UI.HtmlControls;
RenderContents(output);
protected override
void CreateChildControls()
{
Controls.Clear();
CreateControlHierarchy();
}
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);
}

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
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
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.
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.”


<%@ 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.
<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.
<%@ 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>


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.
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);
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)
{
}
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.

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: