Creating a Composite Control:
A Composite Control is derived from the class System.Web.UI.Control.
It also needs to implement the
INamingContainer interface which can create the controls with a unique id.
INamingContainer interface achieves this by creating a unique namespace for the Custom server control placed on an aspx page.
Many of the web controls like Repeater, DataGrid etc., which support databinding implement this INamingContainer interface. This is because, these controls internally create a lot of other controls on the fly. This needs uniqueness for the controls as they also allow access to these inner controls.
Our goal of this exercise is to create a composite control as a simple calculator with two text boxes, one dropdownlist, a button and a label control to show the result. This will give us a simplistic view of the whole stuff.
To Create a Composite control, first create a Web Control Library Project under Visual C# Projects. This will create a default WebCustomControl1.cs file, which can be used for creating a control from scratch. But our case is to create a composite control. We can still use this file. Just rename the file and class name to MyCompositeControl.cs.
The next job is to make sure that the class inherits from the Control class and implement the INamingContainer interface. The wizard would have already put in the base class as System.Web.UI.WebControls.WebControl for us. This class is derived from System.Web.UI.Control. Now our job is to add INamingContainer in addition to this. The intellisense in VS .Net is so intuitive that, when typing in this INamingContainer it will prompt us to press the tab key to include the members to be implemented. But as INamingContainer does not have any members, this is not necessary.
public class MyCompositeControl : System.Web.UI.WebControls.WebControl, INamingContainer
{
}
Also the VS .Net would have added a function inside the class definition, which will be used while creating a control from scratch. This function has to be deleted now. If this function is kept, then the resultant page will try to display the code from this function and it'll confuse the programmers.
The CreateChildControls function should also be overridden. When we type protected override VS .Net automatically lists all the overridable member functions and we can choose our CreateChildControls function. Add the following code for this function.
/// <summary>
/// This CreateChildControls should be used to write code for
/// creating our composite controls
/// </summary>
protected override void CreateChildControls()
{
TextBox text1 = new TextBox();
TextBox text2 = new< TextBox();
DropDownList ddlist1 = new DropDownList();
Button cmdResult = new Button();
Label lblResult = new Label();
text1.Height = Unit.Pixel(25);
text1.Width = Unit.Pixel(70);
text1.Text = "0";
text2.Height = Unit.Pixel(25);
text2.Width = Unit.Pixel(70);
text2.Text = "0";
ddlist1.Height = Unit.Pixel(25);
ddlist1.Width = Unit.Pixel(40);
ddlist1.Items.Add("+");
ddlist1.Items.Add("-");
ddlist1.Items.Add("*");
ddlist1.Items.Add("/");
cmdResult.Height = Unit.Pixel(25);
cmdResult.Width = Unit.Pixel(50);
cmdResult.Text = "Result";
lblResult.Height= Unit.Pixel(25);
lblResult.Width = Unit.Pixel(200);
lblResult.Text = "Result Will be displayed here";
LiteralControl lc = new LiteralControl("<br>");
cmdResult.Click +=new EventHandler(cmdResult_Click);
Controls.Add(text1);
Controls.Add(ddlist1);
Controls.Add(text2);
Controls.Add(cmdResult);
Controls.Add(lc);
Controls.Add(lblResult);
}
private void cmdResult_Click(object sender, EventArgs e)
{
Label lblResult = (Label)Controls[5];
try
{
TextBox text1 = (TextBox)Controls[0];
DropDownList ddBox = (DropDownList)Controls[1];
TextBox text2 = (TextBox)Controls[2];
this.EnsureChildControls();
switch(ddBox.SelectedValue)
{
case "+":
lblResult.Text = Convert.ToString(Convert.ToInt32(text1.Text)+Convert.ToInt32(text2.Text));
break;
case "-":
lblResult.Text = Convert.ToString(Convert.ToInt32(text1.Text)-Convert.ToInt32(text2.Text));
break;
case "*":
lblResult.Text = Convert.ToString(Convert.ToInt32(text1.Text)*Convert.ToInt32(text2.Text));
break;
case "/":
lblResult.Text = Convert.ToString(Convert.ToInt32(text1.Text)/Convert.ToInt32(text2.Text));
break;
}
}
catch(Exception eVal)
{
lblResult.Text = eVal.ToString();
}
}
One other useful point to be noted is, when we add the Event Handler code for the button for the cmdResult.Click, the intellisense again prompts us to press the <TAB> to create the handler code automatically. Once tab is pressed, it creates our function signatures automatically and we can go in and type our logic inside the handler.
The above code takes input of the numbers and displays the result of the selected arithmetic operation. It does not do any advanced error handling except displaying the Exception message.
The above controls will not be visible on the Visual Studio .Net designer, as this needs a designer class to be created for the composite control. Read the next page on Adding the Designer code and Using the composite control.
Attachments
Project Files Composite Controls Sample