Thomas Bandt

Über mich | Kontakt | Archiv

ASP.NET Templating & Interfaces

Aus aktuellem Anlass habe ich mal ein klitzeklitzekleines Beispiel zusammengestellt, das zeigt, wie man mit Interfaces UserControls (oder in diesem Beispiel einfach ein WebForm) ganz elegant und einfach zu Templates machen kann.

Das ist z.B. dann angebracht, wenn man dynamische Inhalte aus einer Datenbank ausliest und mehrfach dynamisch ausgibt. Dann kann man jedem Datensatz einfach ein UserControl als Template zuweisen, und in diesem dann dem Designer seinen Freiraum lassen - nirgendwo muss, wenn man es geschickt anstellt, hardcoded HTML generiert werden.

Noch eine kurze Erklärung dazu:

Der grundlegende Gedanke ist der, dass man Logik aus den Templates raushalten kann, und trotzdem annähernd 100% flexibel ist, bei dem, was man darstellt, d.h. was ein Template enthält oder eben nicht.

Als allererstes definiert man also eine Basisklasse, von der zukünftig alle Templates erben. Im Beispiel ist das wie angesprochen eine WebForm, es kann aber genauso gut (und sinnvoller) ein UserControl sein. Diese muss von Page bzw. UserControl erben:

public class BaseTemplate : Page
{
    public BaseTemplate()
    {
    }
}

Als nächstes definiert man ein Interface für einen Bereich, der im Template gerendert werden soll. Das kann eine Überschrift, ein Einleitungstext, eine Liste von Bildern o.ä. sein. Der Einfachheit halber hier nur das aktuelle Datum:

public interface ISetDate
{
    void SetDate(Control c);
}

Damit der Sache nun Leben eingehaucht werden kann, braucht es noch eine Methode, die im Konstruktor der Basisklasse aufgerufen wird, und die sich um den Inhalt kümmert:

private void SetDate()
{
    if(this is ISetDate)
    {
        Literal currentDate = new Literal();
        currentDate.Text = DateTime.Now.ToLongDateString();
        ((ISetDate) this).SetDate(currentDate);
    }
}

Zuerst wird geprüft, ob das Interface überhaupt implementiert ist - das ist der eigentliche Vorteil der Geschichte. Denn ein Template muss nicht alle Interfaces und damit Funktionen des Gesamtpaketes beinhalten. Wenn das Interface also nicht implementiert ist, passiert nichts.

Aber wenn, dann wird hier ein neues LiteralControl generiert, welches als Text das aktuelle Datum bekommt. Noch ein Vorteil: definiert man im Interface das übergebene Objekt abstrakt als Control, kann man evtl. an Stelle des LiteralControls auch ein HyperLink-Control generieren, oder was auch immer einem einfällt - und das natürlich Abhänigkeiten unterwerfen.

Zu guter Letzt noch die eigentliche Implementierung im Template:

public partial class _Default : BaseTemplate, ISetDate
{
    public void SetDate(Control c)
    {
        Page.Controls.Add(c);
    }
}

Von der Basisklasse erben, ISetDate-Interface implementieren, fertig. Was man dann mit dem übergebenen (Literal-) Control anstellt, ist einem selbst überlassen, bzw. kann individuell von Template zu Template geregelt werden.

Fazit

Meiner Meinung nach bietet das Konzept die völlige Freiheit, ist ziemlich elegant und wenig kompliziert (wenn man es erstmal verstanden hat) sowie leicht erweiterbar. Ich setze es in dieser Form jetzt schon seit zwei Jahren in unserem CMS ein, und bin damit bis jetzt sehr gut gefahren.

Anhängend ein ausführbares Beispielprojekt.

Downloads

Kommentare

  1. Christian Hünniger schrieb am Samstag, 19. Mai 2007 14:19:00 Uhr:

    Danke :-)


    Ich sollte auch viel mehr mit interfaces arbeiten, aber bei mir gibt es immernoch eine vertändnislücke.
    Hast Du vielleicht mal einen sehr guten Link oder sowas?


    Danke


« Zurück  |  Weiter »