CompositeControl or WebControl
Whenever possible, i rather to use UserControl instead of WebControl, since WebControls are more complicate to create and later on to maintain.
But in case that i have to build a WebControl, i rather build a CompositeControl.
Way CompositeControl?
CompositeControl eventually inherit from WebControl, but each control inside the CompositeControl manage its own life cycle events and the ViewState / PostBack data.
This means that we going to save a lots of code writing by not handling this events our self's.
Implementing the CompositeControl
Create the following code in a new Class Library:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace BaseType.Composite.Controls
{
public class LoginControl : CompositeControl
{
/// <summary>
/// Occurs when [login submit].
/// </summary>
public event EventHandler LoginSubmit;
/// <summary>
/// Gets or sets the name of the user.
/// </summary>
/// <value>The name of the user.</value>
public string UserName
{
get { return ((TextBox)this.FindControl("UserName")).Text; }
set { ((TextBox)this.FindControl("UserName")).Text = value; }
}
/// <summary>
/// Gets or sets the password.
/// </summary>
/// <value>The password.</value>
public string Password
{
get { return ((TextBox)this.FindControl("Password")).Text; }
set { ((TextBox)this.FindControl("Password")).Text = value; }
}
/// <summary>
/// Called by the ASP.NET page framework to notify server controls that use composition-based
/// implementation to create any child controls they contain in preparation for posting back or
/// rendering.
/// </summary>
protected override void CreateChildControls()
{
TextBox tbUserName = new TextBox();
TextBox tbPassword = new TextBox();
tbUserName.ID = "UserName";
tbPassword.ID = "Password";
Button btLogin = new Button();
btLogin.Text = "Login";
btLogin.Click += new EventHandler(btLogin_Click);
HtmlTable table = new HtmlTable();
HtmlTableRow tr;
HtmlTableCell td;
//Add the UserName textbox
tr = new HtmlTableRow();
td = new HtmlTableCell();
td.InnerHtml = "UserName:";
tr.Controls.Add(td);
td = new HtmlTableCell();
td.Controls.Add(tbUserName);
tr.Controls.Add(td);
table.Controls.Add(tr);
//Add the Password textbox
tr = new HtmlTableRow();
td = new HtmlTableCell();
td.InnerHtml = "Password:";
tr.Controls.Add(td);
td = new HtmlTableCell();
td.Controls.Add(tbPassword);
tr.Controls.Add(td);
table.Controls.Add(tr);
//Add the Login button
tr = new HtmlTableRow();
td = new HtmlTableCell();
td.InnerHtml = " ";
tr.Controls.Add(td);
td = new HtmlTableCell();
td.Controls.Add(btLogin);
tr.Controls.Add(td);
table.Controls.Add(tr);
//Add the Table to this control
this.Controls.Add(table);
}
/// <summary>
/// Handles the Click event of the btLogin control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
void btLogin_Click(object sender, EventArgs e)
{
if (LoginSubmit != null) LoginSubmit(this, e);
}
}
}
Once compiled, you can add the Control to your Toolbox by adding the .DLL file.
Using the LoginControl
After adding the control to your toolbox, all you need to do is to drag him to you designer:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="Test._Default" %>
<%@ Register Assembly="BaseType.CompositeControls"
Namespace="BaseType.Composite.Controls" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<cc1:LoginControl ID="LoginControl1" runat="server"
OnLoginSubmit="LoginControl1_LoginSubmit" />
</div>
</form>
</body>
</html>
You can hook to the LoginSubmit event from designer:
<cc1:LoginControl ID="LoginControl1" runat="server"
OnLoginSubmit="LoginControl1_LoginSubmit" />
After posting the form, you can get the UserName and Password for the LoginControl class already exposed properties, since CompositeControl already managing the ViewState and Postback data for us:
protected void LoginControl1_LoginSubmit(object sender, EventArgs e)
{
Response.Write(LoginControl1.UserName);
}
The Control in action
Enjoy!