Very often we have multiple parts of page that can submit some user information to the server.
We can easily divide parts of our WebForm with ValidationGroups into logical parts that we can validate before the data is submitted.
But if we have on our page more than one ASP.Net Control that can cause postback to the server (for example if we have multiple Buttons, DropDownLists, ImageButtons etc) how can we determine which one of them user clicked to submit the page to the server?
To precisely determine this important bit of information we need a detailed overview on what happens when the WebForm is submitted to the server:
If you lookup the HTML code that ASP.Net generates when you put Form on your page you will find hidden input field named
This is where ASP.Net stores the name of the Control that initiated the postback of the WebForm.
Having the name of the control, we can easily get the reference to the instance of that control via FindControl method of the Page object.
But not always :)
There are two exceptions to this simple rule: when Button and ImageButton controls are clicked on the form.
We need to handle those two cases differently:
Handling the Button control:If a Button control was clicked our field
"__EVENTTARGET" is not assigned.
The only thing we can do to find out the name of the control that submitted the form is to loop trough all the names of the variables in Page.Request.Form collection that is filled for us, and the only one that is the instance of ASP.Net Button class is the Button that caused the postback. This is becasue if Button is causing the postback, the only Button control value that is sent to the server is the one that caused the postback.
Other Button controls are simply ignored and not sent to the server. Is that cool or what?
Handling the ImageButton control:If image button control was clicked to submit the form, very similar sequence of events happen:
Only the ImageButton control that caused the postback is sent to the server, but with a slight difference:
Instead of one variable in this case two form variables are created for ImageControl that caused the postback (and stored in Page.Request.Form collection).
First variable is called the same as ImageControl only with
".x" suffix and the value of that form variable is the relative horizontal position of the mouse pointer inside the ImageControl at the time when it was clicked.
Second variable that is created is named same as the ImageControl but with suffix
".y" and its value is the relative vertical position of the mouse pointer inside the ImageControl at the time when it was clicked.
So if user clicked the top left corner of the ImageControl these variables will both have values 0.
For us it is important to know that first variable submitted that has suffix of
".x" or
".y" is the name of the ImageButton control that caused postback (with suffix) and then we can easily strip the suffix to get the actual name of the ImageButton control.
Note: this will only work if you dont name some other controls on the WebForm with ".x" or ".y" suffix so be careful with that!
Ok here is the method that we can use to retrieve the instance of the control that caused the postback: public static Control GetPostBackControl(Page page)
{
Control postbackControlInstance = null;
string postbackControlName = page.Request.Params.Get("__EVENTTARGET");
if (postbackControlName != null && postbackControlName != string.Empty)
{
postbackControlInstance = page.FindControl(postbackControlName);
}
else
{
// handle the Button control postbacks
for (int i = 0; i < page.Request.Form.Keys.Count; i++)
{
postbackControlInstance = page.FindControl(page.Request.Form.Keys[i]);
if (postbackControlInstance is System.Web.UI.WebControls.Button)
{
return postbackControlInstance;
}
}
}
// handle the ImageButton postbacks
if (postbackControlInstance == null)
{
for (int i = 0; i < page.Request.Form.Count; i++)
{
if ( (page.Request.Form.Keys[i].EndsWith(".x")) || (page.Request.Form.Keys[i].EndsWith(".y")))
{
postbackControlInstance = page.FindControl(page.Request.Form.Keys[i].Substring(0, page.Request.Form.Keys[i].Length-2) );
return postbackControlInstance;
}
}
}
return postbackControlInstance;
}
And here is an example on how to use that method in our Page: protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
Control cause = GetPostBackControl(Page);
// use the control, typecast it etc
}
}
Have fun!