Adding Events
A natural part of control development is for the control to expose events that make it easier to interact with the control. The constituent controls of a control are not automatically exposed to users. To expose events, you can define an event for the control and raise that event in response to a change in state or an event of constituent controls. The code in Listing 4 shows how to raise a new event when the user clicks the "Visit Jane Doe's Web Site" link shown in Figure 1.
Listing 4 A Control Event
// notify user that site link was clicked public event EventHandler Click; // callback on Author's Site link click protected void AuthorSite_Click(object sender, EventArgs e) { EnsureChildControls(); // raise event if (Click != null) { Click(this, EventArgs.Empty); } // move to author's site Page.Response.Redirect(AuthorSite); }
As Listing 4 shows, there's nothing special about the basic code required to raise an event. Because the Click event of the AuthorBio control is public, it will appear on the Events tab of the Object Inspector, making it easy for web forms to hook up callbacks.
Recall that controls in a designer normally have a default event, and C#Builder generates code if you double-click the control on the design surface. You can achieve the same behavior by adding a DefaultEvent attribute to the AuthorBio control's class definition. Also, handlers for controls are not invoked automatically, as you would normally expect. You must add the INamingContainer interface to the class definition. The following code shows how to add both a DefaultEvent attribute and the INamingContainer interface.
[DefaultProperty("Text"), DefaultEvent("Click"), ToolboxData("<{0}:AuthorBio runat=server></{0}:AuthorBio>")] public class AuthorBio : System.Web.UI.WebControls.WebControl, INamingContainer { // class definition elided for clarity }
In the code snippet above, the DefaultEvent attribute identifies the Click event. In addition to letting the IDE generate code when the control is double-clicked, the default event gets the initial focus in the Object Inspector when you select the Events tab. The INamingContainer is a marker interface, meaning that it doesn't have members. When this control is rendered with its page, INamingContainer will let each item have a unique name and ensure that everything, including events, is processed okay.