Kategorie: ASP.NET


#ASP.NET: UserControl dynamisch laden

11. August 2009 - 08:45 Uhr

Webseiten sind nicht immer statisch verdrahtet. Manchmal benötigt man eine Möglichkeit, UserControls dynamisch nachzuladen. Mit Hilfe von ein wenig Code geht sowas ohne großen Aufwand.

Gegeben sei ein einfaches UserControl TextDisplay.ascx, das eine TextBox anzeigt oder alternativ den eingegebenen Text darstellt:

<%@ Control Language="C#" ClassName="TextDisplayControl" %>
<script runat="server">
   /// <summary>
   /// Zugriff auf den angezeigten Namen
   /// </summary>
   public String Text
   {
      get
      {
         return tbName.Text;
      }
      set
      {
         tbName.Text = value;
      }
   }

   /// <summary>
   /// Behandelt das PreRender-Ereignis
   /// </summary>
   protected override void OnPreRender(EventArgs e)
   {
      // Überprüfen, ob ein PostBack stattgefunden hat
      if(!IsPostBack)
      {
         // Initial das Eingabefeld anzeigen
         ToggleVisibility(true);
      }

      // Daten binden lassen
      DataBind();

      // Weiter verarbeiten lassen
      base.OnPreRender(e);
   }

   /// <summary>
   /// Schaltet die Sichtbarkeit der PlaceHolder um
   /// </summary>
   private void ToggleVisibility(bool showEnterText)
   {
      // Anzeige umschalten
      phEnterText.Visible = showEnterText;
      phShowText.Visible = !showEnterText;
   }

   /// <summary>
   /// Aktiviert die Texteingabe
   /// </summary>
   protected void EditText(object sender, EventArgs e)
   {
      // Eingabefeld anzeigen lassen
      ToggleVisibility(true);
   }

   /// <summary>
   /// Aktiviert die Textausgabe
   /// </summary>
   protected void ShowText(object sender, EventArgs e)
   {
      // Ausgabefeld anzeigen lassen
      ToggleVisibility(false);
   }
</script>
<asp:PlaceHolder runat="server" ID="phEnterText">
   <div>Ihr Name</div>
   <div><asp:TextBox runat="server" ID="tbName" /></div>
   <div><asp:Button runat="server" ID="tbButtonShow"
      Text="Anzeigen" OnClick="ShowText" /></div>
</asp:PlaceHolder>
<asp:PlaceHolder runat="server" ID="phShowText">
   <div>Hallo, <asp:Label runat="server" Text="<%# tbName.Text %>" /></div>
   <div><asp:Button runat="server" ID="tbButtonEdit"
      Text="Bearbeiten" OnClick="EditText" /></div>
</asp:PlaceHolder>

Dieses Steuerelement verfügt über zwei Buttons, deren Ereignisbehandlungsmethoden ShowText und EditText die Umschaltung der beiden Platzhalter, in denen sich die Eingabe- bzw. Ausgabe-Elemente befinden, steuern. Dabei kommt der Standard-ASP.NET-Ereignisverarbeitungsmechanismus zu Einsatz.

In einer Page oder einem übergeordneten Steuerelement wird dieses Control nun dynamisch geladen. Dabei kommt die Methode LoadControl() der Page- bzw. Control-Klasse zum Einsatz. Diese nimmt als Parameter den relativen oder absoluten Pfad zum zu ladenden Steuerelement entgegen. Wichtig dabei ist, das sich das Steuerelement innerhalb des Applikationsverzeichnisses befinden muss – ein Steuerelement aus einem anderen Verzeichnis lässt sich so nicht laden.

Beim Init-Ereignis des ladenden Steuerelements findet der eigentliche Aufruf von LoadControl() statt. Bezogen auf die Ereignisreihenfolge ist Init eines der sehr am Anfang stehenden Ereignisse und möglicherweise nicht ideal bezogen auf das Auslesen von Informationen aus dem Benutzerkontext (Session), denn dieser steht hier noch nicht zur Verfügung. Soll jedoch die Ereignisbehandlung innerhalb des zu ladenden Steuerelements wie gewohnt ablaufen, ist der Eintritt des Init-Ereignisses der beste Zeitpunkt – spätere Events würden dazu führen, das innerhalb des geladenen Steuerelements unter Umständen keine ordnungsgemäße Abarbeitung der Lebenszyklen stattfinden kann (ViewState wird nicht richtig geladen, Events werden nicht korrekt geworfen, etc.).

Nachdem das Steuerelement geladen worden ist, liegt es als Instanz vom Typ Control vor, ist also eher generischen Charakter. Ist jedoch der Klassenname bekannt, kann die geladene Instanz in den konkreten Typ konvertiert werden. Damit sind sämtliche typspezifische Eigenschaften und Methoden erreichbar und können manipuliert werden.

Zuletzt muss das Steuerelement einem anderen, in der Seite befindlichen Steuerelement zur Anzeige zugewiesen werden. Dies geschieht mit Hilfe der Add()-Methode von dessen Controls-Auflistung.

Der Code einer Seite, die das Steuerelement TextDisplay.ascx lädt und einbindet, sieht letztlich so aus:

<%@ Page Language="C#" %>
<script runat="server">

   /// <summary>
   /// Behandelt das Init-Ereignis der Seite
   /// </summary>
   protected override void OnInit(EventArgs e)
   {
      // Laden des Controls
      Control textDisplay = LoadControl("~/TextDisplay.ascx");

      if(!IsPostBack)
      {
         // Control in den konkreten Typ umwandeln
         TextDisplayControl tdc = textDisplay as TextDisplayControl;

         // Initialen Text setzen
         tdc.Text = "Karsten";
      }

      // Control an den PlaceHolder anfügen
      phData.Controls.Add(textDisplay);

      base.OnInit(e);
   }

</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
   <head runat="server">
      <title>Eingabeseite</title>
   </head>
   <body>
      <form id="form1" runat="server">
         <h1>Hier können Sie Ihren Namen eingeben</h1>
         <div>
            <asp:PlaceHolder runat="server" ID="phData" />
         </div>
      </form>
   </body>
</html>

Falls Sie sich fragen, woher in Zeile 15 der Klassenname TextDisplayControl stammt: Der wurde in der Control-Deklaration mit Hilfe des Attributs ClassName definiert:

<%@ Control Language="C#" ClassName="TextDisplayControl" %>

Ruft ein Benutzer die Seite im Browser auf, erhält er initial folgende Ausgabe:

Eingabeseite - Opera

Gibt er einen Namen ein und betätigt die Schaltfläche Anzeigen, wird zur zweiten Ansicht gewechselt:

Eingabeseite - Opera (2)

Der Wechsel auf die Eingabeseite zurück geschieht durch Klick auf die Schaltfläche Bearbeiten.

Zusammenfassend bleibt festzuhalten: Steuerelemente lassen sich dynamisch über die Methode LoadControl() nachladen. Sie können anschließend in ihren konkreten Typ konvertiert werden. Wichtig ist, das dieser Prozess so zeitig wie möglich im Lebenszyklus der Seite stattfindet, damit die Ereignisse und Verarbeitungen des dynamisch nachgeladenen Steuerelements korrekt verarbeitet werden können.

Kommentieren » | ASP.NET, Tipp

#ASP.NET: Ausgabe manipulieren

11. Juli 2009 - 00:12 Uhr

Angenommen, Sie würden eine Webseite betreiben, die etwa BB-Code oder anderen Pseudocode für Formatierungen von Ausgaben verwendet. Sie hätten dann die unangenehme Aufgabe, ein entsprechendes Umformatieren aller BB-Code-Tags in die entsprechenden HTML-Tags bei jeder Ausgabe vorzunehmen. Da wäre es doch angenehmer, dies zentral erledigen zu lassen.

Für genau diesen Zweck ist die Eigenschaft Filter der HttpResponse-Klasse geschaffen worden. Diese erlaubt es, eine eigene Stream-Implementierung zu definieren, die eine Ausgabe … naja, filtert. Dabei ist das Schwierigste, diese Implementierung zu entwickeln, jedenfalls dann, wenn man nicht weiß, wie man es anstellen soll.

Die Lösung: Einfach die vorhandene Stream-Implementierung im Konstruktor des eigenen Streams übergeben lassen, in einer Instanzvariablen speichern und dann überall verwenden. Der eigene Filter erbt dabei zwingend von der Basisklasse System.IO.Stream und implementiert die abstrakten Methoden dieser Klasse.

Weiterlesen »

Kommentieren » | .NET, ASP.NET, Tipp