Introduction
In addition to using Web Server controls in your ASP.NET web pages, you can create your own custom, reusable controls using the same techniques you use for creating ASP.NET web pages. These controls are called User Controls. A User Control is a kind of composite control that works much like an ASP.NET web page - you can add existing web server controls and markup to a User Control, and define properties and methods for the control. You can then embed them in ASP.NET web pages, where they act as a unit.
User Controls are semi-autonomous pages of HTML and underlying ASP.NET code that can be inserted into ASP.NET pages. As such, they are useful for adding blocks of functionality to pages.
Typical uses of User Controls are for use as page headers and footers. Unlike ASP.NET pages that have the .aspx file extension, User Controls typically have the .ascx file extension. Once created, in Visual Studio .NET, they can be included in a specific page by simply dragging the User Control onto the Design view of that page. Alternatively, they can be added to a page at Design time by including the following in the page's HTML. For example, the following line includes a SimpleControl
User Control from the SimpleControl.ascx file:
<%@ Register src="~/usercontrols/SimpleControl.ascx"
tagname="SimpleControl" tagprefix="SimpleControl" %>
The User Control is then positioned on the page using the following tag:
<SimpleControl:SimpleControl id="ucSimpleControl"
runat="server"></SimpleControl:SimpleControl>
Although this procedure is satisfactory for content like headers and footers that will always be required on specific pages, it would be useful if there was a way of dynamically loading specific User Controls at run time.
Fortunately, it is possible to load User Controls onto a page by making use of the LoadControl
method. This function has a straightforward syntax - it takes a single argument - the virtual path to the User Control page. For example, to load the SimpleControl
User Control, the following C# code would be used within the Page_Load
method, or you can use this on the Click
event of the button:
usercontrols_SimpleControl ucSimpleControl =
LoadControl("~/usercontrols/SimpleControl.ascx")
as usercontrols_SimpleControl;
Once the User Control has been loaded, it can be added to the page by adding it to the Controls
collection:
Placeholder1.Controls.Add(ucSimpleControl);
Using the Code
First, let's create a User Control and populate it with several controls. The User Control content looks like this:
<table>
<tr>
<td><asp:Label ID="label1" runat="server"
Text="First Name" ></asp:Label></td>
<td> <asp:TextBox ID="txtFirstName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label ID="label2" runat="server"
Text="Last Name" ></asp:Label></td>
<td> <asp:TextBox ID="txtLastName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Button ID="btnPost" runat="server"
Text="Send Info" OnClick="btnPost_Click" />
</td>
</tr>
</table>
Create a delegate just under the namespaces to handle the Click
event in the Default.aspx page. After declaring the delegate, create the delegate instance which will be called from the virtual method of the btnPost
's click.
public delegate void btnPost_Click(object sender, System.EventArgs e);
public partial class usercontrols_SimpleControl :
System.Web.UI.UserControl
{
#region Public Event
public event btnPost_Click btnPostClk;
#endregion
#region Public Properties
public TextBox FirstName
{
get
{
return txtFirstName;
}
set
{
txtFirstName = value;
}
}
public TextBox LastName
{
get
{
return txtLastName;
}
set
{
txtLastName = value;
}
}
#endregion
#region Vitual Methods
protected virtual void OnbtnDelQtnMrClk(EventArgs e)
{
btnPostClk(this, e);
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnPost_Click(object sender, EventArgs e)
{
OnbtnDelQtnMrClk(e);
}
}
Now, go to the ASPX page where you want to add the User Control and register the User Control by registering the tag in HTML view. The ASPX page content looks like this:
<%@ Register src="~/usercontrols/SimpleControl.ascx"
tagname="SimpleControl" tagprefix="SimpleControl" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>This is example of how to add usercontrol dynamically</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAddControl" runat="server"
Text="Click to add SimpleControl"
onclick="btnAddControl_Click" />
<br />
<asp:PlaceHolder runat="server"
ID="Placeholder1" ></asp:PlaceHolder>
<br />
<asp:Label ID="lblUser"
runat="server"></asp:Label>
</div>
</form>
</body>
</html>
To add the User Control on the Click
event of "btnAddControl
", add the following code to the code-behind:
protected void btnAddControl_Click(object sender, EventArgs e)
{
usercontrols_SimpleControl ucSimpleControl =
LoadControl("~/usercontrols/SimpleControl.ascx")
as usercontrols_SimpleControl;
ucSimpleControl.FirstName.Text = "Milind";
ucSimpleControl.LastName.Text = "Chavan";
ucSimpleControl.btnPostClk +=
new btnPost_Click(ucSimpleControl_btnPostClk);
Placeholder1.Controls.Add(ucSimpleControl);
Session.Add((Session.Count + 1).ToString(), ucSimpleControl);
createAgain = true;
}
void ucSimpleControl_btnPostClk(object sender, EventArgs e)
{
usercontrols_SimpleControl ucSimpleControl =
((usercontrols_SimpleControl)(sender));
lblUser.Text = "Welcome " + ucSimpleControl.FirstName.Text +
" " + ucSimpleControl.LastName.Text;
}
The most important thing is, after the postback, the User Control vanishes from the page. So to maintain the User Control and its controls' properties as well as events, we need to add this instance of the User Control to the session variable shown above. To generate the User Control again on postback, we use the OnPreInit
event:
const string controlID = "MyUserControl";
static bool createAgain = false;
protected Control GetPostBackControl(Page page)
{
Control control = null;
try
{
string ctrlName = page.Request.Params.Get("__EVENTTARGET");
if (ctrlName != null && ctrlName != String.Empty)
{
control = page.FindControl(ctrlName);
}
else
{
ContentPlaceHolder cph =
(ContentPlaceHolder)page.FindControl("Main");
for (int i = 0, len = page.Request.Form.Count; i < len; i++)
{
string[] ctl = page.Request.Form.AllKeys[i].Split('$');
if (ctl.Length > 2)
{
control = cph.FindControl(ctl[2])
as System.Web.UI.WebControls.Button;
}
if (control != null) break;
}
}
}
catch (Exception ex)
{
throw ex;
}
return control;
}
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
Control control = GetPostBackControl(this.Page);
if ((control != null && control.ClientID ==
btnAddControl.ClientID) || createAgain)
{
createAgain = true;
CreateUserControl(controlID);
}
}
protected void CreateUserControl(string controlID)
{
try
{
if (createAgain && Placeholder1 != null)
{
if (Session.Count > 0)
{
Placeholder1.Controls.Clear();
for (int i = 0; i < Session.Count; i++)
{
switch (Session[i].ToString())
{
case "ASP.usercontrols_simplecontrol_ascx":
{
usercontrols_SimpleControl ucSimpleControl =
LoadControl("~/usercontrols/SimpleControl.ascx")
as usercontrols_SimpleControl;
ucSimpleControl.FirstName.Text =
((usercontrols_SimpleControl)(Session[i])).FirstName.Text;
ucSimpleControl.LastName.Text =
((usercontrols_SimpleControl)(Session[i])).LastName.Text;
ucSimpleControl.btnPostClk +=
new btnPost_Click(ucSimpleControl_btnPostClk);
Placeholder1.Controls.Add(ucSimpleControl);
break;
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
I know this is one of the known techniques, but I hope it has given you another way to think about dynamically adding controls. Enjoy!
History
- 18th February, 2010: Initial post
- 4th June, 2010: Uploaded VB source code