Multiple Update Panels - asp.net

When you have multiple UpdatePanels on a page, is there a way, in the code behind, find out which Update Panel triggerred the postback? It appears that the Request["__EVENTTARGET"] is not a reliable way of doing this.

An UpdatePanel doesn't trigger PostBacks, it intercepts them. The originator of the PostBack would be something like a button. If you have event handlers for all your interactive elements, you naturally know which one fired by which event handler runs.

you can get the id of the postback element on the client with the following
function pageLoad(sender, args) {
// add function to the PageRequestManager to be executed on async postback initialize
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
}
function InitializeRequest(sender, args) {
if(args._postBackElement.id === 'id_of_element_in_question' {
// do whatever
}
}
to get it on the server, presumably you'll know which control/event raised the postback as it will be handled in the relevant event handler in the code-behind.

Related

How do I perform a partial post back after the page loads on the client?

I have some processing that can take up to 5+ seconds the first time the page is loaded on the server. This is an external constraint that's beyond my control and since it's happening in a WebPart that can be added to any page on servers that are outside of my control, I can't do this processing at a larger scope such as the application.
I'd like the page to show progress while a partial postback happens in an updatepanel instead of the user waiting for the page to load before seeing anything at all. The code behind that postback will do the busy work.
I've tried using an ajax timer which works well except when there's an exception thrown in the code behind the postback.
In summary I would like to know how to perform a partial postback once and only once as soon as the page loads on the client.
I figured this out. To partial postback to the server via an UpdatePanel without using hidden controls, do this with jQuery:
<script type="text/javascript">
$(document).ready(function () {
__doPostBack('<%=UpdatePanel1.ClientID %>');
});
</script>
This will perform a partial postback to the server against the UpdatePanel with the ID UpdatePanel1 as soon as the HTML DOM is ready. You can then use the ASP.NET page life cycle to hook into whatever event is appropriate for you. I hooked into the load event of the update panel:
protected void UpdatePanel1_Load(object sender, EventArgs e)
{
if (Page.IsPostBack && Session["InitializedKey"] == null)
{
Session["InitializedKey"] = true;
// do your initialization stuff here
}
}
The code above will only run if the page is posting back and the session variable is set. Now you have to clear the session variable when the user refreshes the page since the intent here is to run this code on the first postback and only the first postback. So clear the session variable in the Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
Session[initializedKey] = null;
}
And if you want to show a progress indicator while the page is in partial postback, do this javascript:
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginRequestHandler);
prm.add_endRequest(EndRequestHandler);
function BeginRequestHandler(sender, args) {
if (args._postBackElement.id == '<%=UpdatePanel1.ClientID %>') {
$get('Progress').className = 'Progress';
}
}
function EndRequestHandler(sender, args) {
if (sender._postBackSettings.sourceElement.id == '<%=UpdatePanel1.ClientID %>') {
$get('Progress').className = 'Hidden';
}
}
</script>
This requires a div tag with the id 'Progress' and whatever you want to show for progress within that div. You also need some css to set the display and visible styles on the div tag in classes named Hidden and Progress. Don't forget to perform error handling on partial postbacks!

two events fired simultaneously in ASP.NET

I have an update panel in my ASP.NET web form with a trigger that will fire a click event when the contents within my update panel is updated (it's a grid view with fields). The event that is fired when then take the changes user made and do some calculation and then update another update panel with that information. This is all fine and dandy when the user tabs along the form and fill out the form in a orderly fashion before hitting any buttons on the page.
If a user accidentally hits another button on the page while changing the content in my grid within the update panel, for example, the user enter a value in my grid view control, without tabbing, the user click the save button.
Logically, i believe that the trigger should fire the click event first (event A), and then the save button event (event B). But, consistently I haven't seen event A gets fire correctly while event B gets fire all the time ...
any thoughts on this?
is there a way to ensure event A always gets fired before event B?
also if event A update another update panel without the page will event B fire after the update is complete?
thanks.
You can try to block the form from post 2 times before gets update. Here is an example
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
var fAlloToSubmit = true;
function AllowFormToRun()
{
if(!fAlloToSubmit)
alert("Please wait for the page to fully re-loaded.");
return fAlloToSubmit;
}
function InitializeRequest(sender, args) {
fAlloToSubmit = false;
}
function EndRequest(sender, args) {
fAlloToSubmit = true;
}
and on code behind add the onsubmit.
protected void Page_Load(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(Page.Form.Attributes["onsubmit"]))
{
Page.Form.Attributes["onsubmit"] = "return AllowFormToRun();";
}
}

generate ajax postback for only one updatepannel in javascript

when I click a button the content inside my updatepannel changes. The id of the button is set as a trigger for the updatepannel, so that the other updatepannels are not affected.
How can I replace the buttonclick event with a page load event?
Is there a way to specify the pageload javasript event as a trigger for the updatepannel?
There's no way to register pageLoad() as a trigger, but you can call __doPostBack() in that function to force your UpdatePanel to refresh itself. However, that will cause an infinite loop if you're not careful, because pageLoad() is also called when partial postbacks complete.
One way around that problem is to set a flag before refreshing the panel, and persist that flag in the window object so it survives partial postbacks:
function pageLoad()
{
if (!this.panelRefreshed) {
this.panelRefreshed = true;
__doPostBack("yourUpdatePanelClientID", "");
}
}

ASP.NET AJAX Server Control - Detecting Instantiation of Control

I am creating a custom .NET AJAX Server Control, and need to get access to the JavaScript object functionality associated with that control. I can do this by finding the control in the ScriptManager using the $find method. However, I need to determine when I can call $find. If I do this on the "onload" event of the body of my HTML page, it can't find the control. Thus I end up having to locate the control with each event I wire up and my code ends up looking like this:
function button1_click() {
var control = $find("<%=Control.ClientID%>");
control.DoSomething();
}
function button2_click() {
var control = $find("<%=Control.ClientID%>");
control.DoSomethingElse();
}
I would rather store that control once, and use it throughout the rest of my event calls. Thus I'm hoping the code would eventually look something like this:
var _control = null;
function load() {
_control = $find("<%=Control.ClientID%>");
}
function button1_click() {
_control.DoSomething();
}
function button2_click() {
_control.DoSomethingElse();
}
Let me know if this doesn't make sense. I am new at creating these custom controls, so I'm not quite sure of the terminology yet. Thanks for your help!
The "load" DOM event occurs before the ASP.NET Ajax client-side framework is initialized. Client-side controls are initialized by handling the init event of the Sys.Application object. That's why an ASP.NET Ajax control's initialization script is output like:
Sys.Application.add_init(function() {
$create( ... )
});
You can use the load event of the Sys.Application object or its shortcut- the pageLoad method. It occurs after the init event and all ASP.NET Ajax controls will be initialized then. Here is some sample code:
var _control = null;
function pageLoad() {
_control = $find("<%= Control1.ClientID %>");
}

How to set a timer in asp.net

I have a page where when some operation goes wrong i want to start the timer, wait 30 second, stop the timer and retry the operation. Every time the timer starts I need to inform the user about it by changing some label's text.
How can I do it?
If I understand correctly, the I think you should use a client-side (javascript) timer instead. You can not use a server-side timer for this.
When you detect the error-condition, you update the label accordingly and display it to the user. At the same time you invoke a client-side timer which will postback after 30 seconds.
E.g. put the following timer-code onto your page:
<script>
function StartTimer()
{
setTimeout('DoPostBack()', 30000); // call DoPostBack in 30 seconds
}
function DoPostBack()
{
__doPostBack(); // invoke the postback
}
</script>
In case of the error-condition, you have to make sure that the client-side timer will be started:
if (error.Code == tooManyClientsErrorCode)
{
// add some javascript that will call StartTimer() on the client
ClientScript.RegisterClientScriptBlock(this.GetType(), "timer", "StartTimer();", true);
//...
}
I hope this helps (the code is not tested, since I don't have visual studio available right now).
Update:
To "simulate" a button click, you have to pass to button's client id to the __doPostBack() method, e.g:
function DoPostBack()
{
var buttonClientId = '<%= myButton.ClientID %>';
__doPostBack(buttonClientId, ''); // simulate a button click
}
For some other possibilities, see the following question/answer:
ClientScriptManager.GetPostBackEventReference Method
Call ASP.NET function from JavaScript?
from the client side to force a postback you can directly call the __doPostBack method
It takes two arguments, EVENTTARGET and EVENTARGUMENT; since you are making this call outside the normal asp.net cycle you will need to check IsPostBack on your page load event (or init, your choice) - if it is a postback then you will need to look at those two argument which get rolled up as form elements (Request.Form["__EVENTTARGET"]). Check their value to see if the postback came from your call or one of the other controls, if the value of those matches what you pass in from the client side then make your change to the label test
Two ways to do this, first way,a bit better if you need to call other functions on the same thread. Add a ScriptManager and a Timer to the aspx page, you can drop from toolbox or simply enter the code. ScriptManager must be declared before asp:Timer. OnTick fires after every interval.
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:Timer ID="Timer1" runat="server" Interval="4000" OnTick="Timer1_Tick">
</asp:Timer>
In the code behind (c# in this case):
protected void Timer1_Tick(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("tick tock");
}
Second way not as good if you need the functions to fire on the same thread.
You can do a timer in ASP.net using C#, the following code fires the function every 2 seconds.
In the code behind (.cs) file:
// timer variable
private static System.Timers.Timer aTimer;
protected void Page_Load(object sender, EventArgs e)
{
// Create a timer and set a two second interval.
aTimer = new System.Timers.Timer();
aTimer.Interval = 2000;
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
}
Then make the function you want to call in this format:
//Doesn't need to be static if calling other non static functions
private static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
Sample Output:

Resources