Im ersten Teil dieses Mini-Tutorialshabe ich gezeigt, wie Sie ein simples Button ASP.NET Webcontrol bauen können. Dieses Control leitet von WebControl ab, rendert eigene HTML-Tags und verwendet IPostBackEventHandler, um auf das Javascript onClick Event des Buttons zu reagieren.
Im zweiten Teil dieses Mini-Tutorials entwickeln wir wie versprochen ein eigenes ASP.NET Textbox Control, das ein Subset der bestehenden TextBox Klasse implementiert und die funktionsweise von ASP.NET zeigen soll.
Was ist nun der wesentliche Unterschied eines Buttons zu einer TextBox, könnten sich nun ungeduldige Leser fragen – ist das nicht das Gleiche in Grün?
Der Unterschied zwischen TextBox und Button liegt in der Art des Events und seiner Auslösung: Beim Button reicht es dem Server mitzuteilen, dass der Button gedrückt wurde. Bei der TextBox ändert sich der Textinhalt, also ein Event, das gleichzeitig auch den neuen Inhalt als Übergabewert braucht.
Rendern der HTML Tags
Beginnen wir wieder mit einer neuen Klasse, die wiederum HTML-Tags in der Render Methode in die Seite schreibt.
public class CustomTextbox : WebControl, IPostBackDataHandler
{
protected override void Render(HtmlTextWriter writer)
{
this.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); ;
writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
// Something is missing here -- Point A
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
}
public string Text
{
get { return (string)this.ViewState["Text"]; }
set { this.ViewState["Text"] = value; }
}
static readonly object EventTextChanged = new object();
public event EventHandler TextChanged
{
add{base.Events.AddHandler(EventTextChanged, value);}
remove{base.Events.RemoveHandler(EventTextChanged, value);}
}
}
Binden Sie das CustomTextbox Control (wie in Teil 1 des Mini-Tutorials beschrieben) neben einen Button in ihre Seite ein. Implementieren Sie einen onClick Eventhandler für den Button, um dort mittels eines Breakpoints im WatchWindow den Wert von CustomTextbox.Text zu überprüfen.
Eventverarbeitung
Auch wenn Sie den Text manuell ändern, wird die Text Eigenschaft immer gleich (leer) bleiben.
Das liegt daran, dass die Formulardaten vom Postback erst am Server ausgewertet werden müssen. Dies wird über das Interface IPostBackDataHandlergemacht. Dieses definiert zwei Methoden:
public bool LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
if (this.Text != postCollection[postDataKey])
{
this.Text = postCollection[postDataKey];
return true;
}
else
return false;
}
public void RaisePostDataChangedEvent()
{
EventHandler handler = (EventHandler)base.Events[EventTextChanged];
if (handler != null)
handler(this, EventArgs.Empty);
}
In LoadPostData haben wir über die postCollection Zugriff auf alle Formularwerte, postDataKey ist der Key des jeweilige Controls. In der Implementierung vergleichen wir, ob der neu gepostete Formularwert der TextBox anders ist, als der bisherige. Ist dies der Fall (der Rückgabewert true), so wird automatisch RaisePostDataChangedEvent aufgerufen. In dieser Methode können wir implementieren, wie ein Event gefeuert werden soll, falls sich Daten verändert haben.
Die Eventverarbeitung läuft nun wie folgt ab:
- Textbox Inhalt wird geändert
- Click auf den Button löst Postback zum Server aus
- Da die Textbox IPostBackDataHandler implementiert, wird LoadPostData aufgerufen
- Gepostete Daten sind anders als der Letztstand aus dem ViewState
- Text Inhalt wird am Server (und im ViewState) verändert
- TextChanged Event wird am Server gefeuert.
- Button – Click Event wird am Server gefeuert.
Eine mögliche Schwäche liegt im Postback: Erst wenn ein anderes Control (z.B. Button) einen Formular Postback zum Server auslöst, werden auch die neuen Textboxwerte verarbeitet.
Wichtig: Wenn TextChanged & Button.Click Events beim gleichen Postback gefeuert werden (wie hier), passiert dies immer zuerst für alle xxxChanged Events, dann für alle Submit/Click-Events. (Man könnte auch sagen, IPostBackDataHandler wird vor IPostBackEventHandler aufgerufen).
Auto-Postbacks
Die Lösung für das oben beschrieben Problem heißt Auto-Postback. Sobald sich der Inhalt des HTML-Input Controls ändert, soll sofort ein Postback zum Server gemacht werden, ohne auf spätere Button-Clicks oder andere Aktivitäten zu warten.
Um Auto-Postback zu implementieren, benötigen wir eine neue Eigenschaft:
public bool AutoPostBack { get; set; }
Wenn AutoPostBack am Control aktiviert ist, können wir in der Render Methode (an Point A) im Falle des onChange Javascript Events einen manuellen Postback rendern:
if (this.AutoPostBack)
{
writer.AddAttribute(HtmlTextWriterAttribute.Onchange,
this.Page.ClientScript.GetPostBackEventReference(this, ""));
}
Das würde ein clientseitiges HTML-Input Tag bewirken, das so aussieht:
<input type="text" value="Meine Textbox"
onchange="__doPostBack('CustomTextbox1','')" />
Download: Beispielcode zum Mini-Tutorial
knom