The previous article introduced the basic concepts of implementing custom server control events. This article will explain how to capture callback events through typical examples.
1. Implement capturing postback events.
If a server control needs to capture postback events from the client and wants to customize server-side event processing logic for the postback events, then the control must implement the System.Web.UI.IPostBackEventHandler interface. The interface definition is listed below.
public interface IPostBackEventHandler
{
void RaisePostBackEvent(string eventArgument);
}
As shown in the above code, the IPostBackEventHandler interface only includes one member method RaisePostBackEvent. This method enables the server control to handle events raised when the form is sent to the server. Its parameter eventArgument represents the optional event parameters to be passed to the event handler. Developers can implement the logic performed during the server control postback process in the RaisePostBackEvent method. Typically, the RaisePostBackEvent method will raise one or more server-side events. The following code snippet shows the RaisePostBackEvent implementation that raises the Click event on the server.
public void RaisePostBackEvent(String eventArgument)
{
OnClick(EventArgs.Empty);
}
To achieve capturing postback events, it is not enough to just make the server control class implement the IPostBackEventHandler interface and implement the member methods of this interface. Developers also need to pay attention to implementing other things. Listed below are three key points in the process of capturing postback events.
First, and most importantly, the custom server control class must implement the IPostBackEventHandler interface and implement the interface member RaisePostBackEvent method. This process has been described above.
Second, assign a UniqueID to the control.
Defining the name attribute value of the control that causes the postback event to be UniqueID is one of the keys to correctly implementing the RaisePostBackEvent method. When a postback is triggered, the page framework searches for the content being sent and determines whether the name of the sending object corresponds to the UniqueID of the server control that implements IPostBackEventHandler. If corresponding, the page framework will call the RaisePostBackEvent method on the control. The key point here is that developers need to assign UniqueID to the name attribute of the control in the rendering logic. A simple code example is listed below.
protected override void Render(HtmlTextWriter output)
{
output.Write("<INPUT TYPE=submit name="+this.UniqueID+"Value='Click Me' />");
}
As shown in the above code, in the control rendering method Render, a button is presented, whose name attribute value is UniqueID. Only when the name attribute of the control that causes the postback is assigned a UniqueID can the postback event be captured correctly.
Third, implement the event attribute structure.
The event attribute structure is an optimized way to implement events. Before introducing, let's first look at the common control event implementation methods. The specific code is as follows.
...
public class WebCustomControl:WebControl,IPostBackEventHandler{
//Declare the Click event delegate public event EventHandler Click;
//Implement the RaisePostBackEvent method void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
OnClick(EventArgs.Empty);
}
//Define OnClick event handler protected virtual void OnClick(EventArgs e) {
if(Click != null) { Click(this,e); }
}
...
}
In the above code, three key contents related to event definition are included: 1. Define the Click event delegate; 2. The control class implements the IPostBackEventHandler interface, in which the event handler OnClick is defined when implementing the interface member method RaisePostBackEvent. ;3. Implement the OnClick event handler. The above implementation method is simple and easy to use, but it has a shortcoming, that is, low execution efficiency. Especially when multiple events are triggered in a class, it will increase overhead, waste a lot of server resources, and ultimately lead to reduced operating efficiency.
In order to solve the above problems, an optimized event implementation method-event attribute structure is introduced below. This structure uses the System.ComponentModel.EventHandlerList class, which provides a simple delegate list. By using the related methods provided by this class, developers can flexibly manipulate the control's event handler delegate list. For example, the Click event in the control uses the event attribute structure as follows:
protected static readonly object EventClick = new object();
public event EventHandler Click{
add {
Events.AddHandler(EventClick,value);
}
remove {
Events.RemoveHandler(EventClick,value);
}
}
Before defining the event attribute structure, you first need to define the Click event delegate object. Since each event is only created once, it needs to be declared static and read-only. Then, operate the event handler delegate list through the AddHandler and RemoveHandler methods in the property structure. When the page calls the Click event, it adds or removes handlers from the control's EventHandlerList collection. Since this implementation method is more efficient than the ordinary implementation method in the declaration process of multiple events, it is a very recommended method.
In addition, during the implementation of the OnClick method, when using an event attribute, the delegate must be retrieved from the EventHandlerList and converted to the EventHandler type.
protected virtual void OnClick(EventArgs e){
EventHandler clickHandler = (EventHandler)Events[EventClick];
if(clickHandler != null) {
clickHandler(this,e);
}
}
Please note to readers: The event attribute structure is not applicable to VB.NET language and can only be applied in languages such as C#.
2. Typical applications
To be honest, the above theoretical introduction to capturing postback events is somewhat difficult to understand for readers who have never implemented server control events. To this end, this section uses a typical example to specifically illustrate the implementation method of capturing return events.
This example implements a custom server control WebCustomControl. Although this control appears as a button, it does not inherit from the Button class. When the button is clicked, the control will cause a postback, and the server will automatically capture the click event returned, trigger the Click event, and execute the corresponding event handler. The following is the source code of the server control implementation:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace WebControlLibrary{ [DefaultEvent("Click")] [ToolboxData("<{0}:WebCustomControl runat=server></{0}:WebCustomControl>")] public class WebCustomControl : WebControl, IPostBackEventHandler { //Define a Click event delegate object private static readonly object EventClick = new object(); //Implement Click event properties [Description("Click event properties"), Category("Action") ] public event EventHandler Click { add { Events.AddHandler(EventClick, value); } remove { Events.RemoveHandler(EventClick, value); } } // Override the control rendering method RenderContents protected override void RenderContents(HtmlTextWriter output) { output.Write("<input type='submit' name=" + this.UniqueID + " value=Please click/>"); } //Implement event method protected virtual void OnClick(EventArgs e) { EventHandler clickHandler = (EventHandler)Events[EventClick]; if (clickHandler != null) { clickHandler(this, e); } } // Implement IPostBackEventHandler interface member void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) { OnClick(EventArgs.Empty); } } } |
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <%@ Register TagPrefix="cc" Namespace="WebControlLibrary" Assembly="WebControlLibrary" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> void wcc1_Click(object sender, EventArgs e) { message.Text = "You just clicked the button above"; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Capture postback events</title> </head> <body> <form id="form1" runat="server"> <center> <cc:WebCustomControl ID="wcc1" runat="server" OnClick="wcc1_Click" /> <br /> <br /> <asp:Label ID="message" runat="server"></asp:Label> </center> </form> </body> </html> |
Figure 1 Page initialization renderings Figure 2 Effects after clicking the button |
//Define the attribute AutoPostBack public bool AutoPostBack{ set { this._autoPostBack = value; } get { return this._autoPostBack; } } //Add the Page.GetPostBackEventReference() method in the Render method protected override void Render(HtmlTextWriter output){ ... if(this.AutoPostBack) { writer.WriteAttribute("ontextchanged","javascript:" + Page.GetPostBackEventReference(this)); } ... } |