Why is IsPostBack skipping through my code? - c#

I'm trying to decide using switch case which operation to take where ever section i choose to enter in the page, thus when posting back it will take the right action.
This is the button (Note, this is not the button i'm posting with, rather the one where i enter the section of editing credentials)
<input type="button" value="Edit credentials" onclick="ShowWindow('#EditDetails', 2500); <%WhatToDo = "ChangeUserInfo";%>" />
Code-behind:
public string WhatToDo = "";
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
switch (WhatToDo)
{
case "ChangeUserInfo": ChangeUserInfo();
break;
}
}
}
protected void ChangeUserInfo(){ something }
The posting seems to work, other than the fact that it doesn't run the switch case...
don't know what to do and what am i doing wrong.. If anyone knows what am i doing wrong it'll be great :)

You hook up events in ASP.Net, ASP.Net hides the request and response object for you and wraps it into an Event Driven Architecture . So you don't need to handle the button being pressed in the Page_Load. Instead you need:
Server side button in the .aspx:
<asp:Button runat="server" ID="cmdResubmit" OnClick="cmdAddBooking_Click" Text="Resubmit" />
and an event with the same name as the OnClick in the code behind:
protected void cmdAddBooking_Click(object sender, object e)
{
//put code button code here
SomeClass.value = 123;
SomeClass.StringValue = "1234";
//etc. etc.
}
notice the name of the method matches: OnClick="cmdAddBooking_Click" in the button!
That's it. If you want multiple buttons then add multiple <asp:Button> with multiple event attached to them.
Note:
Clicking a button also triggers a page load (and your event) so any code in the Page_Load event will run on every button click. You can avoid this by wrapping it in if (IsPostBack), this means the code inside this if statement will only run on load not on postback

Related

How can I run a event handler before Page.IsPostBack

I want to run code in a button event handler but the if(Page.IsPostBack) conditional is running first and contains a redirect so the event never runs.
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
(do some stuff with save button pressed...)
// then return the same page to prevent another post on refresh
Response.Redirect(Request.Url.AbsoluteUri);
}
}
and on that page there is another button that calls a handler:
protected void Export_Click(object sender, EventArgs e)
{
(do other stuff..)
}
Is there a way to run the handler first or a way to check which button was clicked so I can add a conditional to the redirect?
Thanks.
This behavior is actually by design in WebForms. To keep things stateless, a full postback occurs whenever you wish to fire off a server-side event.
So the short answer is no, you cannot force your event to occur before the Page_Load does.
However, you can restructure your design a bit to get the behavior you desire. At the moment, it looks as though you are depending on a PostBack having a occurred to execute your save logic. Instead of handling the logic in your Page_Load event, it could be handled in an event appropriate to how your user is expecting to save.
If saving is triggered through a button press, then moving logic for handling the save and redirect to a Save_Click event will allow other events related to PostBack to execute their own logic as well.

C# dynamically created user control button click not working

I have a page (company.aspx) that when you click a button on the page the button click event (btnShowDeptsUserControl_Click) dynamically creates a user control and adds to a placeholder. The page reloads with the user control displayed. That works fine.
The issue I am having is that when I click the button on the user control itself, the btnEmailDepts_Click event is not fired, but the main page (company.aspx) is reloaded.
I have read that one way to resolve this is to create the dynamic user control in Page_Init, but I am creating the user control from the main page button click. Also, I am not declaring the user control in the code behind of the main page as you would normally, but do have a placehoder within which the user control is added.
I have also read that you can add a delegate to the main page for the user control button click, but the example seemed to have so much necessary code for such a simple thing that I figured there must be a better way.
Here are the relevant code snippets:
company.aspx:
<asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
<asp:PlaceHolder ID="phUserControls" runat="server"></asp:PlaceHolder>
company.aspx.cs:
protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
{
CreateDeptsUserControl();
}
private void CreateDeptsUserControl()
{
phUserControls.Controls.Clear();
var uc = (UserControl)LoadControl("~/controls/ucDepartments.ascx");
phUserControls.Controls.Add(uc);
}
ucDepartments.ascx:
<asp:Button ID="btnEmailDepts" runat="server" Text="Send Email" OnClick="btnEmailDepts_Click" />
ucDepartments.ascx.cs:
protected void btnEmailDepts_Click(object sender, EventArgs e)
{
EmailDepts(); // breakpoint here is never hit
}
private void EmailDepts()
{
// do something
}
If you read the MSDN, you will notice:
However, the added control does not catch up with postback data processing. For an added control to participate in postback data processing, including validation, the control must be added in the Init event rather than in the Load event.
You are adding your control in the click event which happens after both init and load events, so the postback will not work.
You can call your CreateDeptsUserControl function in the ini event, but there you will have to detect if the btnShowDeptsUserControl was clicked by yourself. It's not hard, you will need to check the submitted values collection and see if there is an item for btnShowDeptsUserControl.
Just wanted to post what I did to make this work. Racil Hilan's answer helped me to arrive at this solution. I did away with the dynamic user control, and went with the more common declared user control in the aspx, but set it to Visible="False" by default.
Notice that the main page button event is empty. Also notice that the user control Page_Load event is empty. All the checking is done in the user control OnInit event, which is executed with each main page load.
In the user control OnInit event I have a couple guard conditions that check to see what EVENTTARGET, if any, caused the page / user control to load. If the EVENTTARGET (control ID) is that of the main page button, then execution will continue and will call LoadSomeData() as well as set the user control Visible = true. Otherwise, if either guard condition evaluates as false, we exit and the user control does not get loaded, so no wasted db / service calls.
company.aspx:
<asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
<uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />
company.aspx.cs:
protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
{
// empty, just need the event for inspection later in user control OnInit event.
}
ucDepartments.ascx:
<asp:Button ID="btnEmailDepts" runat="server" Text="Send Email" OnClick="btnEmailDepts_Click" />
ucDepartments.ascx.cs:
protected override void OnInit(EventArgs e)
{
if (string.IsNullOrWhiteSpace(Request.Params["__EVENTTARGET"]))
return;
var controlName = Request.Params["__EVENTTARGET"];
if (controlName != "btnShowDeptsUserControl")
return;
LoadSomeData(); // call method to load the user control
this.Visible = true;
}
protected void Page_Load(object sender, EventArgs e)
{
// empty
}
private void LoadSomeData()
{
// get data from database
// load table / gridview / etc
// make service call
}
protected void btnEmailDepts_Click(object sender, EventArgs e)
{
EmailDepts(); // this event is now executed when the button is clicked
}
private void EmailDepts()
{
// do something
}
Variation that includes jquery to scroll to user control after postback:
In the main page button click event you can also do something like set a hidden var to a value that can be inspected on main page doc ready to do some jquery stuff, such as scrolling the user control into view if it is far down the page (which I am actually doing in my current task).
Not only will this scroll the now loaded user control into view after clicking the main page button, but notice the code in setupDepts(). I hide the asp button that does a postback to load the user control, and show a regular html button. They both look the same (both say Show Depts), but the regular html button, when clicked, will fire jquery to toggle the div that contains the user control to close, click again, it will open, click again it will close, etc.
This is so that you only load the user control once (make db / service calls once) when the main page button is clicked, and then can toggle show or hide it with subsequent clicks of the alternate button. This approach can be used with multiple buttons or links so long as they all have the same class ids. For example, you may have a Show Depts button / link at top of page and another at the bottom of the page, which is the case in my current task.
company.aspx:
<asp:Button id="btnShowDeptsUserControl" runat="server" class="btnShowDepts" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
<button class="btnToggleDepts" style="display: none;">Show Depts</button>
<div id="divShowDepts" style="display: none;">
<asp:HiddenField runat="server" id="hdnShowDepts"/>
<uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />
</div>
<script language="javascript" type="text/javascript">
$(function () {
toggleDeptsUserControl();
if ($('#<%=hdnShowDepts.ClientID%>').val() === "show")
setupDepts();
});
function setupDepts() {
$('.btnShowDeptsUserControl').hide();
$('.btnToggleDeptsUserControl').show();
scrollToDepts();
}
function scrollToDepts() {
$('#divShowDepts').toggle(700, function () {
if ($(this).is(":visible")) {
$('html, body').animate({ scrollTop: ($(this).offset().top) }, 'slow');
}
});
}
function toggleDeptsUserControl() {
$('.btnToggleDeptsUserControl').on('click', function (event) {
event.preventDefault();
scrollToDepts();
});
}
</script>
company.aspx.cs:
protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
{
hdnShowDepts.Value = "show";
}

Creating an event for a textbox and AJAX Update Panel Control

I wanted to create a "Click" event for a textbox in C# (as there isn't any).
So, this way
protected void Page_Load(object sender, EventArgs e)
{
if (Request["__EVENTARGUMENT"] != null && Request["__EVENTARGUMENT"] == "txt1OnClick")
{
txt1_Click();
}
txt1.Attributes.Add("onclick", this.Page.ClientScript.GetPostBackEventReference(txt1, "txt1OnClick"));
}
private void txt1_Click()
{
ImageMap1.ImageUrl = "guide/1.jpg";
}
Then I wanted to load the image without reloading the page.
So I used the AJAX UpdatePanel Control and this worked fine with
protected void Button1_Click(object sender, EventArgs e)
{
ImageMap1.ImageUrl = "guide/1.jpg";
}
But not with the event I created, because the compiler doesn't identify my new events as
a real event or something I couldn't figure out.
I added the button1_click event according to Step 8 of "Refreshing an UpdatePanel Control with an External Button".
The click event of textbox is not shown in this option:
So my question is is there any way to add this event within System.Web.UI.WebControls.TextBox class or, to make this event visible within the above option?
So that I can include click event of the textbox within the Triggers of the update panel.
If you try to create a Click event for a TextBox, every time a user clicks your textbox you'll trigger a postback to the server (even to evaluate if you need to do something as part of handling the event). This is very inefficient - you should handle clicks in the browser, using JavaScript and then trigger the UpdatePanel using client-side logic.
This lets you trigger a call to the server if you need it but avoid it when you don't. If you have a server-side event handler, your code will post back to the server (reloading the page) every time the user clicks the TextBox.
You can read this link (and others) about using __doPostBack() on the client side to trigger an UpdatePanel to perform a postback.
http://encosia.com/easily-refresh-an-updatepanel-using-javascript/

Making an EventHandler delegate association in (!IsPostBack) doesn't work even on first page load --- why?

Works:
protected void Page_Load(object sender, EventArgs e)
{
myButton.Click += new EventHandler(myButton_Click);
}
Doesn't work:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
myButton.Click += new EventHandler(myButton_Click);
}
}
Now, what I expected in the second example was for the eventhandler to be wired to the button only when it is not a postback (i.e. the first time the page is loaded), and then on any postback, the button would no longer run the method associated with the event. That doesn't seem to be the case --- from the very first load (not a postback), the button does nothing when clicked.
My suspicion is that this is related to the page life cycle --- but I'm not quite sure where this falls into that. If I understand correctly, the method associated with the event gets run after the page has posted back (even if you clicked it on the first time the page loads), but I'm referring to the wiring up of the event to the method with the EventHandler delegate, not the actual running of the associated method.
Note: this is purely an attempt to gain a better understanding of what's going on behind the scenes, and not an attempt to solve a real world problem.
You need to think about how the code is executed with each page request. What happens on the server is that a class instance is created for each request and if the line of code
myButton.Click += new EventHandler(myButton_Click);
is conditional it means the event handler is not wired to the event on postback.
In other words if you write something like
<asp:Button ID="myButton" runat="server" OnClick="myButton_Click" />
This translates to the code you wrote and the event gets wired with each request.
The problem is, the event handler can only trigger when it IS a postback. The wiring of event handlers affects this instance of the class only. When a postback occurs, a new instance of your page is created and the event handler is no longer wired. You need to wire it in order for it to get triggered.
The best thing to do is always wire the event handlers. There's no reason not to.
If it is not a Postback, it means that the user just requested a page (HTTP Get request) with typing the URL in the browser (or clicking a link, or...).
If the user clicked on a button, then the browser makes a HTTP Post request, which on the server side, ASP.NET marks the page that is requested with setting the property IsPostBack to true of the page object.
See the answer on this question.
I guess what you intend to do is disable the button on postback.
You can do that by setting the enabled property to false.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
myButton.Enabled = false;
}
}

Calling a function before Page_Load

I have a button that calls function A()
When I click on it I want the calls to be made in that order:
A()
Page_Load()
Right now it's doing:
Page_Load()
A()
Is there a way around that or is it just by design and there's nothing I can do about it?
The easiest way to do this would be to use a HTML Submit button and check to see if it is in the Form on every postback in Page_Init
public void Page_Init(object o, EventArgs e)
{
if(!string.IsNullOrEmpty(Request.Form["MyButtonName"]))
{
A();
}
}
And in your ASP.NET code:
<Button Type="Submit" Name="MyButtonName" Value="Press Here To Do Stuff Early!" />
I think that will work.
Control events (such as the click events of buttons) are called after page_load. The controls are not guarenteed to be fully initialized prior to page_load. If you really need to call a function before page_load has been called based on whether a button has been pressed you'll have to examine the request to check if the button has been pressed (basically old school ASP)
You need to call your function in the Page_Init. Page_Init will happen before Page_Load.
Here's an Overview of the ASP.NET Page Lifecycle.
Not exactly: ASP.NET will always call Page_Load before handling postback events like Button_Click.
However, you can accomplish what you want by redirecting to your page after handling the postback event. (Using the Post-Redirect-Get pattern.)
Inside your Page_Load method, you can avoid running any relevant code twice by checking to see if it's a postback first:
if (!this.IsPostBack) {
// Do something resource-intensive that you only want to do on GETs
}
As Jeff Sternal answered, The Post-Redirect-Get pattern is a good way of solving a problem like this.
In my circumstances i had a calendar and if you clicked a date it would add that to a scheduler. The scheduler would have buttons on each new date that needed to have onclick functions tied to them.
Because the new row was being added with a linkbutton(on the calendar), in the code the new scheduler date was being added at the Postback event handling meaning that the new set of buttons wouldn't have a command tied to them.
The page life Cycle
Post Get Redirect
I don't think it's possible, at least, not in the way described by your question. When you click a button it will send a request to the server which in turn will start processing it, and follow the ASP.NET Page Lifecycle as posted by Joseph.
Alternatively you could try making an AJAX call to a page without reloading the current one you're on and do whatever processing you require.
This is what you want to do for Page Init is called before Page Load.
Take a look at the ASP.net Page Life Cycle
public void Page_Init(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//CALL YOU FUNCTION A()
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
}
}
If your actual goal here is to have your "page loading code" happen after your event handler runs -- for example, if clicking your button changes something in your database, and you want the updated data to be reflected on the page when it loads -- then you could have your "page loading code" get called from a method that gets called later in the ASP.NET page life cycle than your event handler, such as Page_PreRender, instead of calling it from Page_Load.
For example, here's a simplified excerpt from an .aspx.cs page class that has a button event handler that runs before the page population logic, and a confirmation message that is visible on the page only after the button was clicked:
// Runs *before* the button event handler
protected void Page_Load() {
_myConfirmationMessage.Visible = false;
}
// Runs *after* the button event handler
protected void Page_PreRender() {
// (...Code to populate page controls with database data goes here...)
}
// Event handler for an asp:Button on the page
protected void myButton_Click(object sender, EventArgs e) {
// (...Code to update database data goes here...)
_myConfirmationMessage.Visible = true;
}

Categories

Resources