Showing posts with label postbacks. Show all posts
Showing posts with label postbacks. Show all posts

Wednesday, March 21, 2012

Partial Postback + Extenders (Blast from the Past...)

This seems rather ironic with the issues concerning the extenders after partial postbacks in the newest release. At work, we are still using the CTP release and have not converted to Beta. I am also having problems with my extenders not working after a partial postback. The current page uses 2 main controls. One is a custom control that contains a textbox, calendar, and popup behavior to encapsulate a popup calendar. The other is a custom autocomplete extender. The javascript events are not being fired. (I've verified this by adding debug statements in the javascript that print out if I remove the UpdatePanel, and do not print out when the UpdatePanel is uncommented.

MasterPage's ContentTemplate
--UpdatePanel
--table
--tr
---td
----DetailsView
----Row
-----PopupCalendar Control
----Row
-----Custom AutoComplete
----GridView

I saw one post saying that it was the table causing the problem and that making the table runat="server" fixed his/her problem. Lucky him/her. If the DetailsView uses DefaultMode="edit", then both controls work. If I start in ReadOnly mode and use a partial postback to switch...no-go.

I know that this is an older release, but if anyone has any thoughts or experienced this when they were using the last pre-beta CTP release, I'd really appreciate some help before I rip all of my hair out.

Thanks.

I suspect the problem here is that the UpdatePanel doesn't understand the dynamic loading of the components, which probabaly happens in PreRender after the UpdatePanel has scanned the tree. So when the DetailsView switches modes and popuplates itself, it's too late. Unfortuantely, I'm not sure how to fix it.

One thing you can try is calling DetailsView1.DataBind() in Page_Load.


I had a similar problem with the AccordionExtender in an UpdatePanel and created the following workaround:

1) Get control toolkit source code

2) Add the following class under AjaxControlToolkit\ExtenderBase\ExtendedScriptBehaviorDescriptor.cs:

using System;using System.Collections.Generic;using System.Text;using Microsoft.Web.UI;namespace AjaxControlToolkit.ExtenderBase{/// <summary> /// This is merely a hack to overcome the known limitation of the Ajax 1.0 Beta 2 /// that it is impossible to use control extenders inside UpdatePanel because /// the correspondend Behavior instance is being lost after the async postback. /// The workaround is to register an event handler on page load event of the /// PageRequestManager and to re-create the behaviour in this event handler. /// This class has been only tested for an Accordion control inside UpdatePanel. /// </summary>class ExtendedScriptBehaviorDescriptor: ScriptBehaviorDescriptor {public ExtendedScriptBehaviorDescriptor(string type,string elementID):base(type, elementID) { }protected override string GetScript() {string answer =base.GetScript() +" Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded("+"function (sender, args) {"+" var myBehaviors = Sys.UI.Behavior.getBehaviorsByType($get('" +this.ElementID +"'), " +this.Type +");" +" if(myBehaviors.length == 0) {"+base.GetScript() +" }"+"});";//Known limitation / bug: if you register several extenders of the same type //for the same DOM element, only one of them (anyone) will be re-created //after async postback. Can be easily fixed using a slightly more complex //checking logic in the javascript above.return answer; } }}

3) Find the method GetScriptDescriptors in ExtenderControlBase and change the following:

//Original code (before patch): //ScriptBehaviorDescriptor descriptor = // new ScriptBehaviorDescriptor(ClientControlType, targetControl.ClientID); ExtendedScriptBehaviorDescriptor descriptor =new ExtendedScriptBehaviorDescriptor(ClientControlType, targetControl.ClientID);

4) Compile the control toolkit, reference the new version in your project and try if it works now.

You can use the new class also with extenders not using ExtenderControlBase from the Control Toolkit.


Neat! I've openedwork item 6063 to track this.

Sorry for the delay in replying, I ditched college for the week and went home for Thanksgiving.Wink. Calling DataBind on the DetailsView in the PageLoad event didn't work. Random thought: to match other pages in the project, both the details view and gridview are in the same update panel. I wonder if separating so that the dv and gv each have their own update panel would make a difference.

*starts muttering and switches back to VS.

Edit: If I use DefaultMode="Edit" for the DetailsView, click in the textbox to bring up the popup calendar, and click to advance the month, I get the following:

Alert


In the pre-beta CTP, there is no ScriptBehaviorDescriptor, so if this is even a possible hack, it will need to be a hack of a hack. Is there a CTP equivalent?


We recommend using the latest Beta. There may be issues that would require more investigation using the ctp. A lot of changes were made just to get the toolkit working at the asp.net ajax beta so it would be best to move to the beta and then pursue this investigation.

Partial Postbacks and JScript Changes Previously Made on the Client Side

Hello, thank you in advance for taking the time to read this.

I have a Gridview on which I use client-side JScript to add an empty row (hidden) after binding. I place several hidden DIVS in my Gridview template, and then when a user clicks on one of several "expand" buttons in the Gridview, the empty row is made visible and the innerHTML is swapped from the appropriate hidden DIV. This makes the empty row sort of a "Jack of all trades" in that it can display numerous different things as needed by the user.

I am attaching the JScript function below for reference. The empty DIVS are inserted into the client page in the Codebehind using the Gridview's OnRowDataBound handler, but I have no clue how to add a row dynamically server-side, so I went with the client-side script to get the container row done.

Everything works great until you do a sort. The control is AJAX-enabled, so refreshes through a partial postback. Trouble is that the client-side code that adds all the rows does not fire when the grid is refreshed, so none of the "Expand" icons work after the Gridview has been refreshed, because there is no hidden row to make visible and swap content with.

After all this, my question is: How might I:

A) insert an empty row programatically server-side, or

B) fire a client-side script at databinding on a partial postback.

Oh, and I am a pure short-busser when it comes to .NET -- love it but am just now moving up from legacy and feel like a complete idiot. Please speak slowly if you care to answer, and forgive my ignorance.

Javascript adding the rows follows -- I am assigning an ID reference to each row using the "Tracking" field - a unique DB column.

Thanks again for reading, and for any information or hlp you can provide.

Shannon

function fixGrid(idGrid){

var al ="";

var rowcount = 0;for (var t=0;t<idGrid.childNodes[0].childNodes.length-1;t++){

thisName = idGrid.childNodes[0].childNodes[t].nodeName;

if(thisName=="TR"){

rowcount ++;

if(rowcount > 1){

lastCell = idGrid.childNodes[0].childNodes[t].childNodes.length;

thisCell = idGrid.childNodes[0].childNodes[t].childNodes[lastCell-1];

thisTrack = idGrid.childNodes[0].childNodes[t].childNodes[lastCell-2].innerText;

newTR = document.createElement('tr');

newRow1 = newTR.cloneNode(true);

newTD = document.createElement('td');newCol1 = newTD.cloneNode(true);

newCol1.colSpan=9;

newCol1.style.visibility='hidden';

newCol1.style.display='none';

newCol1.id ="td-"+thisTrack;

newCol1.innerHTML="Nothing";

newTR.appendChild(newCol1);

nextRow = idGrid.childNodes[0].childNodes[t].nextSibling;

tableTop = idGrid.childNodes[0].childNodes[t].parentNode;

tableTop.insertBefore(newTR,nextRow);

t++;

}

}else{

alert(thisName);

}

}

returnfalse;

}

Problem solved! I figured I would answer myself for the benefit of future readers.

The call to the client side code in my original post is made fromfixGrid(document.all.gridedit)when the page originally loads.

Obviously, I only want to add the empty container rows once, so I only want this script to be called once each time UpdatePanel1 refreshes, and not if any other panel does. Got it to work that way usingRegisterClientScriptBlock with the update panel ID:

protectedvoid Page_PreRender(object sender,EventArgs e)

{

string script =@."fixGrid(document.all.gridedit);";ScriptManager.RegisterClientScriptBlock(

UpdatePanel1,

typeof(Page),

"ToggleScript",

script,

true);

}

partial postback doing full postback - bug in ATLAS ?

theres no rhyme or reason, but my partial postback button often does full postbacks and then reverts to partial postbacks for no apparent reason...

I can't find anything on this and was suggested that this is a bug in the current release of ATLAS. Does anyone have any idea on this ?

I'm bashing my head trying to figure this one out ..


Thanks very much

mike123

hello.

well, that is strange. do you have a simple demo page that reproduces this?


I'm sorry I don't have one at this time ... =[ I could get it online if you think its crucial to see it to help diagnose

any ideas ?

thanks very much


well, we have to see the server side code to help you diagnoise. an online sample doesn't give us that.


The actual code doesnt really show too much but here it is anyways

I'm really lost on where to go from here. Anyone have any ideas ? I was so psyched about using ATLAS but it's pretty frustrating not being able to get past this point.

Thanks again,

mike123

<formid="form1"runat="server">

<asp:TextBoxId="textbox1"runat="server"/>

<atlas:ScriptManagerID="ScriptManager1"runat="server"EnablePartialRendering="true"/>

<divstyle="background-color: Yellow; float: left; width: 100px;">

<asp:LabelID="FullPostBackLabel"runat="server"/><br/>

<asp:ButtonID="FullPostBackButton"runat="server"text="Full Post Back"OnClick="FullPostBackButton_OnClick"/>

</div>

<atlas:UpdatePanelrunat="server"ID="UpdatePanel1"Mode="Conditional">

<ContentTemplate>

<divstyle="background-color: Lime; width: 100px;">

<asp:LabelID="PartialPostBackLabel"runat="server"/><br/>

<asp:ButtonID="PartialPostBackButton"runat="server"text="Partial Post Back"OnClick="PartialPostBackButton_OnClick"/>

</div>

</ContentTemplate>

</atlas:UpdatePanel>

<atlas:UpdateProgressID="UpdateProgress1"runat="server">

<ProgressTemplate>

Please wait... </ProgressTemplate>

</atlas:UpdateProgress>

</form>

PublicSub FullPostBackButton_OnClick(ByVal senderAsObject,ByVal eAs EventArgs)

FullPostBackLabel.Text = DateTime.Now.ToString()

EndSub

PublicSub PartialPostBackButton_OnClick(ByVal senderAsObject,ByVal eAs EventArgs)

PartialPostBackLabel.Text = DateTime.Now.ToString() &"Partial"

EndSub


hello.

this is weird. i tried running your page in an empty atlas site and it worked without anyproblems...have you tried running this page in a site created through the atlas template?


No I haven't as this is a pretty large web application that needs to have atlas running on it. I don't think theres a problem with the code either, something to do with integration but no idea where to start. I've tried things such as removing flash from the page and javascript ads.... Still no luck ....

Any ideas?

Thanks very much

mike123


I had a similar problem then I found that it was related to custom javascript code that was calling __dopostback


I had a smiliar problem too. I found that It didnt like my hidden input.

<input type="hidden" name="action" ID="action" value="" />

Once i deleted that everything was fine!


I found out that when removing the following line

<xhtmlConformance mode="Legacy"/>

from web.config , UpdatePanels work like they should

this did not occur in Atlas CTPs, but in AJAX final release...