Custom Control, Postback and Events

Sometime back I was required to write a Custom Control, with some custom Events and some advanced functionality. Since I was not too familiar with the "Art of Writing Controls", I was searching through Google, to get some useful material. After spending sometime, I realized that there are a lot of blogs, articles are out there on custom controls, but none of them are complex and realistic, most of them are "Hello World" kind of an example. Moreover, I found that different people are using some different ways of achieving the same thing. So in this blog I will try to explain what I have learned from that experience, but I may add up to another different approach. Sorry for that. :D

In this post I will try to explain few concepts about Custom controls, mostly related to Postback and Raising Events.

I will use example of a Custom Control, that will not do much of the activities, but it will contain 2 buttons, and it will expose 2 events, one each for each of the button.

Event Handlers

Now to start with the very basic of Event handling in a Custom Control, we need to define a List of type EventHandlerList . EventHandler List will help us to store the Event Handler's associated with each of the Events.

protected EventHandlerList _lstEventHandlers = new EventHandlerList();

Since our control exposes two Events, we will define two key values, so that we can use them as Key values.

static readonly object _prevEventKey = new object();

static readonly object _nextEventKey = new object();

So far we have defined the EventHandlerList and two key values, to use to store the EventHandlers in the List. Now we will define the two Events, those will be Exposed to the Page, that uses this Control.

Remember, how we add EventHandler to an Event? Offcourse using the +=. If we want to expose those two events as Public Properties, then how they should look like? Hmmmm... surely we won't be using get;set;. Rather than that we will be using add; and remove; Sounds a bit confusing ??? Let's look into the code snippet.

public event EventHandler onPreviousButtonClick

{

  add

    {

       _lstEventHandlers.AddHandler(_prevEventKey, value);

    }

  remove

    {

       _lstEventHandlers.RemoveHandler(_prevEventKey, value);

    }

}

 Similarly for the Next Button Click, we will define another Event say "onNextButtonClick"

public event EventHandler onNextButtonClick

{

  add

    {

       _lstEventHandlers.AddHandler(_nextEventKey, value);

    }

  remove

    {

       _lstEventHandlers.RemoveHandler(_nextEventKey, value);

    }

}

Now we will look into most important section, how to wire up PostBack and how to Raise Events.

Since I have two buttons, in the CreateChildControls() function, will add two LinkButtons, and give them ID's.

LinkButton _lnkNext = new LinkButton();

_lnkNext.ID = "NextButton";

LinkButton _lnkPrev = new LinkButton();

_lnkPrev.ID = "PrevButton";

Why we require ID's? hmmm, we will require these ID's sometime later. One quick point here, whenever you are creating any Custom Control, better to Implement "INamingContainer" interface. So far we have defined the events, and created the controls. But we haven't added any code to write the famous "__doPostback" function. So in the CreateChildControl method we will add the following code.

_lnkNext.Attributes.Add("href", Page.GetPostBackClientHyperlink(_lnkNext, this.ClientID));

_lnkNext.Attributes.Add("name", _lnkNext.ClientID);

_lnkPrev.Attributes.Add("href", Page.GetPostBackClientHyperlink(_lnkPrev, this.ClientID));

_lnkPrev.Attributes.Add("name", _lnkPrev.ClientID);

 

Postback 

The above code snippet will add the Hyperlink and it will make sure that it will do a Postback. Now we will Use "IPostBackDataHandler" interface so that we can notify ASP.NET engine that this Control Participates in  PostBack, and this control will have an opportunity to the values and decide whether to Raise any Event or Not.

This interface defines two methods,

public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection);

public void RaisePostDataChangedEvent();

The first method will fire just after Page_Init, but before Page_Load. If the PostBack is caused by our control, then we will return true, else we will return false. So in LoadPostData, we will write the below code snippet.

public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)

        {

            string _target = postCollection["__EVENTTARGET"];

            string _arg = postCollection["__EVENTARGUMENT"];

            if (_arg == this.ClientID)

            {

                if (_target == "NextButton")

                {

                  //Property, to track which button was clicked.

                    this.NextButtonClicked = true;

                }

                Page.RegisterRequiresRaiseEvent(this);

                return (true);

            }

            else

            {

                return (false);

            }

 

        }

  
 In the above code snippet "__EVENTTARGET", and "" are two values, those were set from the __doPostBack javascript function.  And the "Page.RegisterRequiresRaiseEvent(this);" line will notify the page that, it needs to fire the "RaisePostDataChangedEvent()" method.

In the "RaisePostDataChangedEvent" method, we will simply raise the Events, for the corresponding buttons.

public void RaisePostDataChangedEvent()

  {

EventHandler prevHandler = (EventHandler)_lstEventHandlers[_prevEventKey];

            if (prevHandler != null)

            {

                prevHandler(this, EventArgs.Empty);

            }

            EventHandler nextHandler = (EventHandler)_lstEventHandlers[_nextEventKey];

            if (nextHandler != null)

            {

                nextHandler(this, EventArgs.Empty);

            }

  }

  

Hmmm, we are done..., a Control with multiple Events, is Done. Hope this post will help you.

Question: Why we are firing the Event in "RaisePostDataChangedEvent()", what will happen if we raise the Event in "LoadPostData"?

5 Comments

  • Question: Why we are firing the Event in "RaisePostDataChangedEvent()", what will happen if we raise the Event in "LoadPostData"?

    Answer:
    If you raise the event in LoadPostData it will occur before the Page PreLoad event so, any control you try to change in the event handler will be reloaded and any changes lost.

  • I can't get this to work at all. I can't even find RegisterRequiresRaiseEvent off of the Page ???

  • How can I tigger postback of a control manually ?

  • Hi Guys,
    In all the blogs i read how to raise custom events, by calling (,) in a child control's postback event like,Button_Click events etc., in user control. But I want raise this event without calling in any child control's postback event.
    Please guide me.Just I am thing that, if we call our custom event (,) in any child control's postback,no use of it. Instead of this, directly we can write our code in Child controls postback event.Then what is the use of custom events?

    Thanks & Regards
    Chaitanya

  • Very good article.
    congratulations.

Comments have been disabled for this content.