Von WebControl abgeleitetes CustomControl - Haupt Html Element festlegen
Wenn man ein CustomControl mit ASP.NET entwickeln will, leitet man in den meisten Fällen von WebControl ab.
Zitat aus einem MSDN Artikel: Entwickeln und Verwenden eines benutzerdefinierten Serversteuerelements
Wenn das Steuerelement ein Element der Benutzeroberfläche (UI) oder ein anderes auf dem Client sichtbares Element rendert, sollten Sie das Steuerelement von
System.Web.UI.WebControls.WebControl (oder einer davon abgeleiteten Klasse) ableiten. Falls das Steuerelement ein Element rendert, das im Clientbrowser nicht sichtbar ist, z. B. ein ausgeblendetes Element oder ein
meta-Element, leiten Sie das Steuerelement von
System.Web.UI.Control ab. Die
WebControl-Klasse ist von
Control abgeleitet und fügt formatbezogene Eigenschaften hinzu, z. B.
Font,
ForeColor und
BackColor. Zusätzlich kann ein von
WebControl abgeleitetes Steuerelement die Designfeatures von ASP.NET nutzen, ohne dass für Sie zusätzliche Arbeit entsteht.
Standardmässig wird bei einer Ableitung von WebControl ein Span-Tag als Hauptelement gerendert, dieses Element enthält unter anderem die ClientID des Controls als ID-Attribut.
In den meisten Fällen möchten wir einen anderen Tag als Grundlage verwenden, bspw. einen Div-Tag.
Erklären lässt sich dieses Verhalten, wenn wir einen Blick auf die Implementierung von der Klasse WebControl werfen.
Der Standardkonstruktor ruft den zweiten Konstruktor auf, und übergibt diesem ein HtmlTextWriterTag.Span mit:
protected WebControl() : this(HtmlTextWriterTag.Span)
{
}
Für diesen Fall habe ich im Internet ein "Workaround" gefunden, bei dem man die Methoden RenderBeginTag() und RenderEndTag() überschreibt.
Das Haupt Html Element rendert man inklusive der Unterelemente dann in einer überschriebenen Render() Methode.
Das sieht dann so aus:
public override void RenderBeginTag(HtmlTextWriter writer) {
// do nothing
}
public override void RenderEndTag(HtmlTextWriter writer) {
// do nothing
}
Diese Sache funktioniert auch wunderbar, jedoch hat das auch ein paar Nachteile bzw. die nächste Variante, Vorteile.
- Wir nutzen eine eigene Konstruktion, nicht die bequemen Vorgaben von WebControl
- Die Methoden AddAttributesToRender(), RenderBeginTag(), RenderContents() und RenderEndTag() werden überflüssig und nicht mehr nutzbar
- Es muss mehr geschrieben werden, obwohl es einfacher gehen würde
Intern sieht die Render() Methode von WebControl, die wir ansonsten ja überschreiben, ungefähr so aus:
protected internal override void Render(HtmlTextWriter writer)
{
this.RenderBeginTag(writer);
this.RenderContents(writer);
this.RenderEndTag(writer);
}
Das heisst, wenn das Control mit Render() gerendert wird, werden diese drei Methoden hintereinander aufgerufen.
Diese Aufrufe passieren automatisch, darum müssen wir uns nicht kümmern, so ist es natürlich bequem zu handhaben.
- Erstellen einer Klasse die von WebControl abgeleitet ist
- Im Konstruktor den Basis Konstruktor aufrufen und einen TagNamen für das Control mitgeben
- AddAttributesToRender() Methode überschreiben und mit unseren Attributen füllen
- Die RenderContents() Methode überschreiben und unsere Inhalte rendern lassen
Wie man sieht, ist hier ein schöner Ablauf in Methoden und Methodenaufrufen gegliedert.
Der eigentliche Clou liegt darin, den HtmlWriterTag Enumerationswert im Basiskonstruktor mitzugeben.
Um einen Div Tag als Haupt Html Element für sein Control möchte, kann dieser Konstruktor so aussehen:
// Möglichkeit 1, HtmlTextWriterTag Enum Wert übergeben
public MyControl() : base(HtmlTextWriterTag.Div) {
}
// Möglichkeit 2, String übergeben
public MyControl() : base("div") {
}
Die zweite Möglichkeit kann man für Tags nutzen, die nicht in der Enumeration vorhanden sind.
Wenn man AddAttributesToRender() überschreibt, kann man Attribute an das Haupt Html Element hängen.
Das kann z.B. ein onclick Attribute sein:
protected override void AddAttributesToRender(HtmlTextWriter writer) {
writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "alert('Klappt :-)');");
base.AddAttributesToRender(writer);
}
In RenderContents() rendern wir den Inhalt, und fertig ist unser Render Grundgerüst für das CustomControl.
Fazit:
Wie man sieht, bietet ASP.NET ein super Modell, um die Entwicklung von Controls zu erleichtern. Das Modell ist m.E. logisch und verständlich aufgebaut.
Um das Modell dahinter noch besser zu verstehen, sollte man die .NET Implementation mit dem Lutz Roeders .NET Reflector genauer anschauen, heisser Tipp! :-)
Ein Codebeispiel folgt...