Peter Bucher - Mein Experiment, meine Spielereien, meine Welt...   ·   Stefan Falz   ·   Jürgen Gutsch   ·   Golo Roden   ·   ASP.NET Zone   ·   Microsoft ASP.NET
Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

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.

  1. Erstellen einer Klasse die von WebControl abgeleitet ist
  2. Im Konstruktor den Basis Konstruktor aufrufen und einen TagNamen für das Control mitgeben
  3. AddAttributesToRender() Methode überschreiben und mit unseren Attributen füllen
  4. 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...

Veröffentlicht Donnerstag, 31. Mai 2007 23:59 von Peter Bucher

Kommentare

# Alles neu oder was?

Info & Statistiken Ja, es gibt Neuigkeiten auf meinem Blog, aber es ist nicht alles neu ;-) Unter

Freitag, 24. August 2007 01:45 by Peter Bucher

# re: Von WebControl abgeleitetes CustomControl - Haupt Html Element festlegen

Ich warte jetzt noch auf ein Codebeispiel ;-)

Donnerstag, 4. Oktober 2007 22:27 by thomas77

# Web Server Controls ganz einfach selber machen (Teil 1)

Hiermit starten Peter und ich mal eine kleine Artikelserie zur Erstellung von Web Server Controls. Vielfach

Freitag, 13. Februar 2009 10:09 by Jürgen Gutsch
Anonyme Kommentare sind nicht zugelassen