Introduction
This article covers the following:
- Creating a Web Custom Control.
- Implementing Event / Delegates.
- Implementing Using Designer.
- Implementing OOP Programming (Objects).
Background
What is a Web User Control?
Web user controls are easy to make, but they can be less convenient to use in advanced scenarios. You develop Web user controls almost exactly the same way that you develop Web Forms pages. Like Web Forms, user controls can be created in the Visual Designer, they can be written with code separated from the HTML, and they can handle execution events. However, because Web user controls are compiled dynamically at run time, they cannot be added to the Toolbox, and they are represented by a simple placeholder glyph when added to a page. This makes Web user controls harder to use if you are accustomed to full Visual Studio .NET design-time support, including the Properties window and Design View previews. Also, the only way to share the user control between applications is to put a separate copy in each application, which takes more maintenance if you make changes to the control.
Ref: Recommendations for Web User Controls vs. Web Custom Controls; MSDN.
What is a Web Custom Control?
Web custom controls are compiled code, which makes them easier to use but more difficult to create; Web custom controls must be authored in code. Once you have created the control, however, you can add it to the Toolbox and display it in a visual designer with full Properties window support and all the other design-time features of ASP.NET server controls. In addition, you can install a single copy of the Web custom control in the global assembly cache and share it between applications, which makes maintenance easier.
Ref: Recommendations for Web User Controls vs. Web Custom Controls; MSDN.
Overview
If your control has a lot of static layout, a user control might make sense. If your control is mostly dynamically generated � for instance rows of a data-bound table, nodes of a tree view, or tabs of a tab control � a custom control would be a better choice.
Web User Control |
Web Custom Control |
Easier to create |
Harder to create |
Limited support for consumers who use a visual design tool |
Full visual design tool support for consumers |
A separate copy of the control is required in each application |
Only a single copy of the control is required, in the global assembly cache |
Cannot be added to the Toolbox in Visual Studio |
Can be added to the Toolbox in Visual Studio |
Good for static layout |
Good for dynamic layout |
Ref: Recommendations for Web User Controls vs. Web Custom Controls; MSDN.
Using the code
Style Class
To make a type of property expandable in the PropertyGrid:
TypeConverter(typeof(ExpandableObjectConverter))
Specifies whether a property or event should be displayed in a Properties window.
Browsable(true)
- Specifies the category in which the property or event will be displayed in a visual designer,
- Specifies the default property for a component,
- Specifies a description for a property or event.
Category("Style")
DefaultProertyAttribute("Style")
Description("Style")
Indicates how a designer refreshes when the associated property value changes.
RefreshProperties(RefreshProperties.Repaint)
Represents an attribute of a toolbox item.
ToolboxItem(false)
Indicates that the parent property is notified when the value of the property that this attribute is applied to is modified.
[NotifyParentProperty(true)]
Defines the metadata attribute that specifies how an ASP.NET server control property or event is persisted to an ASP.NET page.
PersistenceMode(PersistenceMode.InnerProperty)
Specifies the type of persistence to use when serializing a property on a component at design time.
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
Returning an empty string.
public override string ToString() { return ""; }
Implementation of StyleClass
:
protected StyleClass cssStyle = new StyleClass();
true),
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
public StyleClass CssStyle
{
get
{
return this.cssStyle;
}
set
{
this.cssStyle = value;
}
}
Item Class
ToTableRow()
method converts the object to a TableRow
for use in the Parent object.
public System.Web.UI.WebControls.TableRow ToTableRow()
{
TableRow itemRow = new TableRow();
itemRow.Cells.Add(new TableCell());
itemRow.CssClass = this.CssStyle.DetailCell;
itemRow.Cells[0].CssClass = this.CssStyle.DetailCell;
LinkButton itemButton = new LinkButton();
itemButton.Text = this.Text;
itemButton.CssClass = this.CssStyle.LinkButton;
itemButton.ID = this.Text;
if(this.DirectLink)
itemButton.Attributes.Add("HREF", this.HREF);
else
itemButton.Attributes.Add("HREF_Link", this.HREF);
itemRow.Cells[0].Controls.Add(itemButton);
return itemRow;
}
Implementation of Item
class:
Item mnuItem = new Item();
mnuItem.Text = ["Menu Item"];
mnuItem.CssStyle = [this.CssStyle];
mnuItem.DirectLink = [true/false];
mnuItem.HREF = [@"http://localhost/"];
[Table].Rows.Add(mnuItem.ToTableRow());
ToolBox Image
Add new Bitmap
item in Project. The name should be exactly same as your control's name.
Bitmap Name = [object Name].bmp
Bitmap Color = 16 Color
Bitmap Width = 16
Bitmap Height = 16
Build Action = Embedded Resource
Main Class
Override OnDataBinding
to implement the [object].DataBind
method:
protected override void OnDataBinding(EventArgs e)
{
this.Controls.Clear();
menuTable = new Table();
menuTable.Rows.Add(new TableRow());
menuTable.Rows[0].Cells.Add(new TableCell());
menuTable.Rows[0].CssClass = this.CssStyle.HeaderCell;
menuTable.Rows[0].Cells[0].CssClass = this.CssStyle.HeaderCell;
Label lblHeader = new Label();
lblHeader.Text = this.HeaderText;
lblHeader.CssClass = this.CssStyle.HeaderLabel;
menuTable.Rows[0].Cells[0].Controls.Add(lblHeader);
Controls.Add(menuTable);
foreach(System.Data.DataRow itemRow in this.DataSource.Rows)
{
Item mnuItem = new Item();
mnuItem.CssStyle = this.CssStyle;
mnuItem.DirectLink = false;
mnuItem.HREF = itemRow[this.ItemColumnHref].ToString();
mnuItem.Text = itemRow[this.ItemColumnText].ToString();
menuTable.Rows.Add(mnuItem.ToTableRow());
}
base.OnDataBinding (e);
}
[DefaultProperty("Text"),
ToolboxData("<{0}:FlatMenu runat="server"></{0}:FlatMenu>"),
Designer(typeof(MyWebCustomControls.FlatMenu .Designer)),
Serializable()]
DataTable dt = new DataTable();
dt.Columns.Add("ColA");
dt.Columns.Add("ColB");
dt.Columns.Add("ColC");
dt.Columns.Add("ColD");
DataRow dr = dt.NewRow();
dr[0] = "Item A";
dr[1] = "http://localhost/Item A";
dr[2] = "Item A";
dr[3] = "Item A";
dt.Rows.Add(dr);
this.Flat1.DataSource = dt;
this.Flat1.ItemColumnText = "ColA";
this.Flat1.ItemColumnHref = "ColB";
this.Flat1.DataBind();
Compile the control. On your toolbox, right click and go to Add / Remove Items, click Browse, and find the compiled DLL. Open / OK, and you will see the Flat Menu on your Toolbox.
Delegates
public delegate void MenuItemCreateHandler(string Text,
string URL, System.Web.UI.WebControls.TableCell currentCell);
public delegate void MenuItemSelectedHandler(string Text, string URL);
Implementation:
MenuItemSelectedHandler onItemSelected;
public event MenuItemSelectedHandler MenuItemSelected
{
add
{
onItemSelected += value;
}
remove
{
onItemSelected -= value;
}
}
MenuItemCreateHandler onItemCreate;
public event MenuItemCreateHandler MenuItemCreated
{
add
{
onItemCreate += value;
}
remove
{
onItemCreate -= value;
}
}
Usage:
if (onItemCreate != null)
onItemCreate (this.Text, this.HREF, itemRow.Cells[0]);
if (onItemSelected!= null)
onItemSelected (this.Text, this.HREF);