UpdatePanel breaks after adding UpdateProgress - asp.net

I have some code that contains a panel where I put an ASP chart from codebehind. Below the panel I placed a button with a postback event that changes some parameter of that chart.
Here is a simplified version of the code:
...
<asp:UpdatePanel ID="udp" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl_chart" runat="server" />
<asp:Button ID="btn_chart" UseSubmitBehavior="false" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
...
And the code behind:
Private Property AltChart As Boolean
Get
If Me.ViewState("simulador_avanzado") Is Nothing Then
Return False
End If
Return ToBool(Me.ViewState("simulador_avanzado"))
End Get
Set(value As Boolean)
Me.ViewState("simulador_avanzado") = value
End Set
End Property
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
...
If IsPostBack AndAlso ToStr(Me.Request("__EVENTTARGET")).Contains("btn_chart") Then
AltChart = Not AltChart
End If
Dim cht as New Chart
'Build the chart...'
pnl_chart.Controls.Add(cht)
...
End Sub
This works like a charm, but when I add an UpdateProgress the PostBack stops working. Whenever I click the button, the UpdateProgress is shown for 2-3 seconds (exactly what it takes to do the PostBack) but then it hides and the UpdatePanel content isn't refreshed.
This is the new code:
...
<asp:UpdatePanel ID="udp" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl_chart" runat="server" />
<asp:Button ID="btn_chart" UseSubmitBehavior="false" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="udpro" AssociatedUpdatePanelID="udp" DynamicLayout="false" runat="server">
<ProgressTemplate>
<div class="udp_progress">
</div>
</ProgressTemplate>
</asp:UpdateProgress>
...
I debugged the partial postbacks and the code behind is working as intended, it updates the AltChart variable and the chart itself.
To put it simple: UpdatePanel partial postback works perfectly, but when I add an UpdateProgress bound to it, its content isn't updated on partial postbacks.
Update: I'm getting the next client error:
SCRIPT5022: Sys.InvalidOperationException: Could not find UpdatePanel with ID 'ctl00_Body_ctl02_udp_button'. If it is being updated dynamically then it must be inside another UpdatePanel.
Apparently the js generated by the UpdateProgress is being cached. The UpdatePanel with ID udp_button is from a previous version of the code and it's no longer there (I had the button outside the UpdatePanel and I wrapped it with its own UpdatePanel to make the UpdateProgress aware of the async postback, following this example, now I simply put it inside the chart's UpdatePanel).
Clearing the browser cache does not seem to work (as well as using a different browser).
UPDATE 2: OK, I was mistaken.
udp_button is another UpdatePanel present on the page, it's inside a user control and I hadn't noticed it. I'll try to place some conditional UpdateModes on both UpdatePanels to see if I can prevent the UpdateProgress from updating the wrong UpdatePanel.

I did what I mentioned on the Update 2 and it worked!
Apparently, the javascript code generated by the UpdateProgress control tries to update all UpdatePanels on the page affected by the async postback, and couldn't find an UpdatePanel that was inside a web user control (the ID it was using to look for the panel didn't match the panel ClientID).
Solution: Establish the property UpdateMode="Conditional" for the UpdatePanel inside the web user control, and make it update only when it's needed. This way the web user control isn't updated during the async postback generated by the button, and the UpdateProgress' javascript doesn't try to find it.

Related

How do I prevent __DoPostBack refreshing an ASPX page?

I have a JS function in an ASPX page that performs a __doPostBack to a vb.net code behind. The problem is that it is forcing the page to refresh. How can I prevent this? My code below...
JS:
__doPostBack('', 'test');
VB.NET:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack Then
Select Case Request.Form("__EVENTARGUMENT")
Case "test"
RadMediaPlayer1.Source = url
End Select
End Sub
Thanks!
There is one easy way, and then one hard way.
The first issue? asp.net web pages are in fact designed to near ALWAYS have and endure post-backs.
This quite much means that any button, any combo box, or just about anything on that page to run some code behind WILL cause a page post-back.
And thankfully due to automatic "view state" management, most controls, and even a grid view, or even a combo box selection will correctly maintain its values for you (its view state).
So, if you don't want the whole page to post back and refresh?
Then you can drop in a plane jane asp.net button, and say whatever it is you want to "only update", then try using what is called a update panel.
Try a quick test page like this:
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
</div>
</form>
And our code behind like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = Date.Now
System.Threading.Thread.Sleep(700)
End Sub
Now, I put in a 3/4 of second delay - just to help you see the effects of this (you don't want that delay sleep() in your actual code.
Ok, now run the above page, click on the button. You see the traditional post-back, you see the browser "spinner"/wait occur, and then the text box is updated.
Now, lets use what is called a update panel - and I am going to suggest you try one.
You can even dump/drop the JavaScript you have now.
So, you have to drop into the page a script manager, and then move your content inside of he update panel. It will now look like this:
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
Give above a try - note how the page don't post-back any more? How cool is that!!!
So, add update panel, content template. And move your button, and the adMediaPlayer1 into that panel.
You don't even need to adopt any JavaScript here. Drop in a plane jane button, and just have normal code behind for that button. Say like this:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
RadMediaPlayer1.Source = "some real url goes here"
End Sub
A few things:
While this looks, feels and appears to NOT do a post back and the .net system will wire this up for you automatic - VERY much like a ajax call?
Don't put too much inside of those update panels.
and keep in mind, while this does not seem to do a post back? In fact this results in what we call a "partial" post back. The page load event even will fire.
Note that code behind CAN ONLY now modify controls inside of that update panel. Other controls on the page are off limits. (unless you move them into that update panel also).
But, dump your JavaScript button or code for the post back. Just move in the media control and your button to inside of that up date panel. Give this a try - you not see a post back - you not see the browser "spinner"/wait run at all.
This feature is great - but a not a cure all.
The next way to do this?
Is you can setup what is called a ajax call. This can call code behind, but keep in mind the code behind can't update controls on the page (due to no post-back). If you don't do a post-back, then code behind can't touch controls on the page.
This would suggest that you have a client side button - click on it, it runs JavaScript, calls some code behind, code behind returns a result, and then in JavaScript you stuff/change the URL of the given control. Since you changing that URL in pure JavaScript at this point? You probably don't even need to write or call code behind anyway.
but, try the update panel - they are very useful. But, keep in mind behind, the .net system is doing a bit of fakery to achieve this goal, and what a partial page post- back does occur.
Edit: pass value from js and click button
So, as noted, if you have a post back, you get page refresh!!! - that's what the command does and means!! So, you can't say I dont want to post back and not refresh the page, and then do a post back!!!
However, as noted, your js code is "obviously" a much larger example, and you sharing of JUST the __DoPostBack() in js is as you noted a larger set of code and routines here.
However, I still suggest you use a update panel.
You can keep 99% of your js code now, and just remove the _dopost back.
Move your case statement code to a button. (yes, a button click code stub).
What we THEN do is this:
The js code can figure out and do whatever it needs. Obviously we reach a point in which a VALUE of some type has to be passed to the server. And then what we will do is then use js code to CLICK the button - the ONE inside of the update panel. This will and should prevent a page refresh. And we pass the value by using a asp.net hidden field control (you could even use a hidden text box - but it don't matter - hidden field is probably better).
So, the pattern, and code will look like this:
We drop a button, hidden field, and that other video or whatever control is is the page - all inside the update panel.
then your js code? It runs, gets the final value. We shove that value into a hidden field control, and then use js to click the button - also inside of that panel.
Thus, you move your on load code + case statement to the button click code.
Like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' get value passed from js
Dim strMyValue As String = Me.HiddenField1.Value
Debug.Print(strMyValue)
Select Case strMyValue
Case "test"
Case "zoo"
Case "my fun test"
End Select
End Sub
And the markup is this:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" ClientIDMode="Static" />
<br />
<asp:HiddenField ID="HiddenField1" runat="server" ClientIDMode="Static" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="Button2" runat="server" Text="js post back"
OnClientClick="mypost();return false;"
/>
<script>
function mypost() {
// set value to pass to button click
$('#HiddenField1').val("my fun test")
$('#Button1').click()
}
</script>
</div>
So, in place of your doPostback, you set the hidden field, and then with js click the button. (once you get this workng, then hide the button with style="display:none"
Of course, you proably have a bunch of postback in your code.
So, make a js function called MyPostBack, say like this:
function MyPostBack(sValue) {
// set value to pass to button click
$('#HiddenField1').val(sValue)
$('#Button1').click()
}
Now, you can replace all your _DoPostBack('', 'test')
With MyPostBack('test')
So, in the update panel, put the hidden field, the button, and that other control. And your js code will now "click" that button in the panel.
Note that the js code above does assume you using jQuery. However, you can code in pure js, and not necessary use jQuery short hand as I did above.

How can i update updatepanel with out postpack ASP.net

i have a gridview in updatePanel that i need to update every interval of time
what i have found so far on updating updatepanel is :
<asp:UpdatePanel ID="UpdatePanel2" runat="server" OnLoad="Button1_Click">
<ContentTemplate>
<fieldset>
<legend>UpdatePanel</legend>
<asp:Label ID="Label2" runat="server" Text="Panel created.">
</asp:Label>
<asp:Button ID="Button1" runat="server"
OnClientClick="__doPostBack('UpdatePanel2', '');" Text="Button" />
</fieldset>
</ContentTemplate>
</asp:UpdatePanel>
and this sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Label2.Text = "Refreshed at " & _
DateTime.Now.ToString()
End Sub
though this works fine and update the panel but it postback the whole the page , you can tell when you see all the images reloading in another panel , i'm planning to update this panel every second
Question is How can i update UpdatePanel2 without affecting the other panel with the postback
EDIT
Another Question does any thing runs at the server side DO postback ?
Thanks
As of NET 3.5 there is the Web.UI.Timer control:
Performs asynchronous or synchronous Web page postbacks at a defined interval.
It is able to work with UpdatePanels, ensures that data (e.g. ViewState and updated control values) is not lost, and is "just another WebForm control". However, the Timer must still cause a [partial] postback to go through the page life-cycle and rebind the grid again.
Depending on exact use-case, it may be better to use a true AJAX-approach to minimize the page life-cycle and data size overhead. (Telerik, DevExpress, and other 3rd-party libraries support "lightweight callbacks" for their Grid controls. Even more lightweight variants might include jqGrid.)

update panel does not working for views

i am using updatepanel for a linkbutton so that it doesnot refresh the whole page . on click of that linkbutton i need to set an active view in a multiview control which is working fine without updatepanel.
but when i use updatepanel it doesnoot work. can you help me how to do this
updatepanel code
<asp:UpdatePanel ID="UpdatePanel3" runat="server">
<ContentTemplate>
<asp:LinkButton ID="changephoto" runat="server" ForeColor="Blue" OnClick="changephoto_Click">Change Photo</asp:LinkButton><br /><br />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="changephoto" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
on click event
Protected Sub changephoto_Click(ByVal sender As Object, ByVal e As System.EventArgs)
MultiView_Updates.SetActiveView(View_ChangePhoto)
'bindprofileimage()
End Sub
put the multiview inside the updatepanel.....
If you want set view on click of the linkbutton which is placed inside the update panel, then your Multiview must also be present inside the update panel. Otherwise, the control will not be refreshed.
UpdatePanel controls work by specifying regions of a page that can be updated without refreshing the whole page. An asynchronous postback behaves like a regular postback in that the resulting server page executes the complete page and control life cycle. However, with an asynchronous postback, page updates are limited to regions of the page that are enclosed in UpdatePanel controls and that are marked to be updated. The server sends HTML markup for only the affected elements to the browser.
Using Nested UpdatePanel Controls
UpdatePanel controls can be nested. If the parent panel is refreshed, all nested panels are refreshed also.
The following example shows markup that defines an UpdatePanel control inside another UpdatePanel control. A button in the parent panel triggers an update of the content in both the parent and the child panel. The button in the child panel triggers an update of only the child panel.

how to clear gridview without reloading the page

I have a gridview control on my asp.net page(vb.net). I also have a "cancel" button, that when pressed, is supposed to clear the gridview of it's current contents.
However whenever the cancel button is pressed, it just reloads the page and the gridview is still there with the same data that I wanted clear.
Based on suggestions that I found on stackoverflow, I set the datasource to nothing, but that is not working.
Here is my code for the cancel button:
Private Sub btnCancel_Click(sender As Object, e As System.EventArgs) Handles btnCancel.Click
gvQuizReport.DataSource = Nothing
gvQuizReport.DataBind()
End Sub
Any suggestions would be welcome!
Thanks
You might try:
gvQuizReport.Columns.Clear()
though as #Leniel Macaferi said, hiding the gridview is a possible solution as well.
since you have shown some interest in updatepanels, here is some starter code in case you are unfamiliar:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
If you already have a scriptmanager on your page you don't need to add another (you will get an error). if you have any problems implementing the updatepanel, feel free to post another question, there are plenty of people to help you with it
The code you showed should "clear" the results, but if you do not want anything displayed, you would hide the gridview by using gvQuizReport.Visible = False;
If you really want to clear without reloading the page, you could just use client side script to hide the grid object.
jquery hide

Trigger an update of the UpdatePanel by a control that is in different ContentPlaceHolder

I have a page with two ContentPlaceHolders. One has a DropDown and another UpdatePanel with content.
How can I trigger update to the UpdatePanel by the DropDown's selectedItemChanged event when they are in different ContentPlaceholders?
The following would not work since UpdatePanel1 doesn't know about DropDown1:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
Some content that needs to be updated here...
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="DropDown1" EventName="SelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>
One way is to make an ajax page method that would be called by javascript on the page when DropDown's item is selected. Then in code behind, inside that page method, call UpdatePanel1.Update().
Is there an easier alternative?
From http://msdn.microsoft.com/en-us/library/system.web.ui.asyncpostbacktrigger.aspx
The control that the
AsyncPostBackTrigger references must
be in the same naming container as
the update panel for which it is a
trigger. Triggers that are based on
controls in other naming containers
are not supported.
The workaround is to use the UniqueID of the control that the
trigger is referencing. Unfortunately the UniqueID isn't qualified
until the control has been added to its parent (and its parent
has been added to its parent, all the way up the control tree).
In your code behind, try:
UpdatePanel1.Triggers.Add(new AsyncPostBackTrigger()
{
ControlID = DropDown1.UniqueID,
EventName = "SelectedIndexChanged", // this may be optional
});
In the code-behind file, you should be able to do:
ScriptManager.RegisterAsyncPostBackControl(dropdown1);
You can enforce update any of page UpdatePanels by call updatePanel1.Update() method on server side.
For example during update updatePanel1 on button1.Click call updatePanel2.Update() and both panels will be updated.

Resources