Thursday, February 24, 2011

Capture a Custom Control Event directly on the Web Page

This is actually something simple, but as it envolves delegates and events, it might be a little confusing to those who are not too familiar with it.

When to use it

Sometimes we'll want to change our page design or some control visibility or value according to user interaction, or some other event. That's pretty straightforward when everything we need belongs to our page. However, we could be expecting this 'trigger action' to come from a defined user control. Defined user controls are a group of controls and objects, also containing .NET code in a code-behind file that we develop so that we can use it in various places throughout our application. It follows the same purpose of a method, for example. If we have some control grouping that we'll need to use somewhere else, on another page, make it a defined user control.

When do I need to interact with the page?

There are lots of examples of when you'd want to change something on the page depending on something that is in the defined control. In this case we'll focus on events.
For my example, we'll have a defined control that lets our user chose a panel's backcolor. We must implement that on multiple pages, that's why we've made a user control for it.


As you may already know, you can't see your user control's controls directly from your page, so you can't assign event handlers to their events. But we can expose that event by creating a public event directly on the user defined control.

First let's create our defined control:

<asp:Label runat="server" Text="Choose a background color:" ID="lblColor" />
<asp:DropDownList ID="dropColor" runat="server" AutoPostBack="True" OnSelectedIndexChanged="dropColor_SelectedIndexChanged">
    <asp:ListItem Text="Blue" Value="#0000FF" />
    <asp:ListItem Text="Red" Value="#FF0000" />
    <asp:ListItem Text="Green" Value="#00FF00" />
    <asp:ListItem Text="Yellow" Value="#FFFF00" />

Notice that we've set property AutoPostBack on our DropDownList to true. That way we'll get a postback everytime the selected value changes.

And we'll declare a public event on our defined control code-behind:

public delegate void ColorSelectedDelegate(string value);
public event ColorSelectedDelegate ColorSelected;    

protected void dropColor_SelectedIndexChanged(object sender, EventArgs e)

That way, when the user selects a color, the SelectedIndexChanged event will trigger our public custom event ColorSelected.

Here's our page design:

<%@ Register TagPrefix="usc" TagName="color" Src="~/BackColorControl.ascx" %>

<h1>Painting Class:</h1>
<form runat="server" id="form1">
            <td align="right">
                <usc:color ID="uscColor" runat="server" OnColorSelected="PaintPanel" />
            <td align="left">
                <asp:Panel ID="pnlPaint" runat="server" Width="100px" Height="100px" BorderColor="Black" BorderWidth="2px" />

You can see that we've set property "OnColorSelected='PaintPanel'" when we declared our defined control. That adds the method PaintPanel as a handler to that event. And we're passing the value of the color selected onto our page. So all we have to do next is actually paint the panel:

protected void PaintPanel(string value)
    pnlPaint.BackColor = System.Drawing.Color.FromName(value);

So, making it simple:

We have to declare a public event on our user defined control that will somehow expose the DropDownList's selected value. When we declare the user defined control on a page, we can add handlers to public events with property "On[Event's Name]". That way, we can get our selected value on the page, and apply it elsewhere, or do whatever we want.