Friday, September 4, 2009

Custom Event for your ASP.NET User Control

Custom Event are very useful when you want your ASP.NET User Control to have its own custom events or expose the events of controls within the User Control itself. This allows you to for example create a User Control that has events like MyOkButtonClickEvent and instead of implementing the functionality of that button in your User Control, you can leave it up to the Page or other calling object (such as another User Control) to implement the functionality.

To illustrate my example a little better, let’s assume you have a User Control that you created called UserInputPanel. This control has a textfield and two buttons on it. One button called Cancel and another called OK. We don’t want to implement what happens when either of the buttons is clicked in the User Control itself. Instead, we want the calling object (the Page in this example) to.

There are at least two easy ways to implement this. The difference between the two is that in one case you have a chance to partially implement the functionality in our User Control, in the other, you don’t have that option.

Let’s do the one that give you the least amount of control, but requires the least amount of code.

public partial class UserInputPanel : UserControl
{
public event EventHandler OkButtonClicked;
public event EventHandler CancelButtonClicked;

protected void Page_Load(object sender, Event args e)
{
btnOk.Click += new EventHandler(OkButtonClicked);
btnCancel.Click += new EventHandler(OkButtonClicked);
}
}

In the .aspx page all you have to do is implement the event handlers like you would any other event handlers.

<uc1:UserInputPanel ID="input1" runat="server" OnOkButtonClicked="UserInputOKButton_Click" OnCancelButtonClicked="UserInputCancelButton_Click"/>

In the code-behind (C#) for the Page, you will have two methods that implement the desired functionality.

protected void UserInputOKButton_Click(object sender, EventArgs e)
{
// do stuff here
}

protected void UserInputCancelButton_Click(object sender, EventArgs e)
{
// do stuff here
}


This works great if you want to give the entire implementation details to the calling object, but what if you want to do some validation, provide default behavior, etc how can you do this? Luckily, it is quite easy to extend what we already did. All the code is the same from the calling objects perspective. The only difference is that instead of directly wiring the EventHandlers together, we will create a new one which will give us an opportunity to do what we want to do.

public partial class UserInputPanel : UserControl
{
public event EventHandler OkButtonClicked;
public event EventHandler CancelButtonClicked;

protected void Page_Load(object sender, EventArgs e)
{
btnOk.Click += new EventHandler(btnOk_Click);
btnCancel.Click += new EventHandler(btnCancel_Click);
}

protected void btnCancel_Click(object sender, EventArgs e)
{
// do stuff here

if (CancelButtonClicked != null)
{
CancelButtonClicked(sender, e);
}

// do stuff here
}

protected void btnOk_Click(object sender, EventArgs e)
{
// do stuff here

if (OkButtonClicked != null)
{
OkButtonClicked(sender, e);
}

// do stuff here
}

}

In the above example, we could have use the .aspx page to wire up the click events, but I did it in the Page_Load to be consistent with the other way. The nice thing about this is you can create new events also. You could for example create a new event called OkButtonBeforeClick or OkButtonAfterClick. These are useful when you have partially implemented functionality in the User Control and want to give the calling object more opportunities to fine-tune their functionality.

A side note: Please note that am exposing the EventHandlers as public member variables. This is technically not the Object Oriented way to do it. You should create properties for each event and make the event private instead of what I did, but it just seems so much cleaner this way. Less code :)

No comments: