Roadmap › Custom Controls & Reusable UI Components in .NET — Web Forms to Blazor › Module: Web Forms Controls
Lessons in this course (9)
2. Building a custom server control — rendering, properties and ViewState
Intermediate★ Must knowLesson 2 of 9
csharp
[DefaultProperty(nameof(Amount))]
[ToolboxData("<{0}:MoneyLabel runat=\"server\" />")]
public class MoneyLabel : WebControl // WebControl adds style properties (CssClass, Font, etc.)
{
public MoneyLabel() : base(HtmlTextWriterTag.Span) { }
[Category("Data"), DefaultValue(typeof(decimal), "0")]
public decimal Amount
{
get => (decimal?)ViewState[nameof(Amount)] ?? 0m; // ViewState-backed so it survives postbacks
set => ViewState[nameof(Amount)] = value;
}
[Category("Appearance"), DefaultValue("en-IN")]
public string Culture
{
get => (string?)ViewState[nameof(Culture)] ?? "en-IN";
set => ViewState[nameof(Culture)] = value;
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer); // id, class, style
if (Amount < 0) writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass + " negative");
}
protected override void RenderContents(HtmlTextWriter writer)
=> writer.WriteEncodedText(Amount.ToString("C", CultureInfo.GetCultureInfo(Culture)));
}aspx
<%@ Register Assembly="Shop.Controls" Namespace="Shop.Controls" TagPrefix="shop" %>
<shop:MoneyLabel ID="lblTotal" runat="server" Amount="4500" CssClass="price" />Base classes:
| Base | Use |
|---|---|
Control | Minimal: no style properties; override Render |
WebControl | Adds CssClass, Style, Enabled, tag rendering (RenderBeginTag/RenderContents) |
CompositeControl | Builds child controls (CreateChildControls) — reuse existing TextBoxes/Buttons |
DataBoundControl / CompositeDataBoundControl | Bind to data sources (DataSource, DataBind) |
Existing control (e.g. TextBox) | Extend behaviour (a NumericTextBox) |