I've been messing around with post back handler in ASP.NET today, and I
found out a few points of interest. Firstly, a description of the
two interfaces used with server controls to handle post backs:
IPostBackEventHandler - Implemented by server controls that wish to handle post back events. The
RaisePostBackEvent
method is invoked by the framework when the control that implements
this interface method is the source of a page post back - such as a
submit button. The
RaisePostBackEvent method is expected to call an event delegate on the control, suck as Click.
IPostBackDataHandler - Implemented by server controls that wish to handle posted form data state changes. The
LoadPostData
method is invoked by the framework when the control that implements the
interface method has posted some form data. This method should
compare the posted data (contained in a
NameValueCollection, keyed with
a passed unique post data key) with the data internal to the control,
to see if the user changed the data on the page. This method is
expected to return true if the state of the data has changed. The
framework checks to return value of
LoadPostData and calls the
RaisePostDataChangedEvent method if the return value was true. The
RaisePostDataChangedEvent methods is expected to call a changed event delegate on the control.
Below is is the source code to a couple of server controls that I had implemented to test these interfaces.
Point #1: Initially both controls were not working. After
pulling out some hair, I figured out that each rendered control must
output a "name" attribute with a unique value. Without this attribute
the framework has no way of calling either the
RaisePostBackEvent or
LoadPostData
methods on the correct control instance. Adding an ID field is not
enough, for some reason ASP.NET insists on the "name" attribute.
Point #2:
IPostBackDataHandler
makes no sense on controls that do not change their state between page
posts - duh. Sounds obvious, but that still did not stop me
spending 20 minutes trying to figure out why this interface was not
working on my custom button control.
Point #3: I wanted to know why the string argument passed to the
RaisePostBackEvent
method was null when I rendered my custom button as a regular HTML form
submit button. Even though a simple submit button will cause a post
back or sort - after all a post back is essentially a form submission -
the framework will not interpret the form submit as a true post back
without the __doPostBack JavaScript call. This JavaScript method
has the capacity to pass an argument to the framework during a form a
post. Adding this method to my code was a simple case of
rendering the returned string from the
GetPostBackEventReference method in an "onclick" attribute.
Point #4: When comparing posted data with that of the internal state of
the data in the control, using
LoadPostData,
it helps if the control persists state
of its own data in the first place. For example, when persisting
the text value in my custom text box I used the
ViewState. Had I used a
private member variable to store the internal text value, the
persistence would have been lost for each post back; because a new
instance of each control on the page is loaded for each page request.