I'm using an ASP.NET Accordion control with lots of panes for a data entry form. Within several of the panes are some UpdatePanels, so that some controls within those panels can be enabled or disabled to prevent users from entering values into fields which are precluded by values they've entered elsewhere.
It all works fine, but for some reason, on about half of the occasions where an UpdatePanel postback is triggered (by a specified AsyncPostBack Trigger), the first pane of the Accordion momentarily expands and collapses. This gives that horrible 'flashing' experience you get when a page does a full postback, which is exactly what I'm trying to avoid by using UpdatePanels.
The problem doesn't seem to relate to the contents of the first pane - I tried completely deleting the first pane, so that the second pane became the first, and the same thing happens.
Anybody got any ideas why this is happening and how to fix it?
UPDATED WITH CODE
This is an example of one of the panels. Don't be too offended by the use of a table - it's an actual table, I'm not just using it for layout purposes!
<tr class="grouprow">
<td>Transportation</td>
<td><asp:RadioButtonList ID="rblTransportation" runat="server" RepeatDirection="Horizontal" SelectedValue='<%# Bind("AdmissionTransportation")%>' AutoPostBack="true"
OnSelectedIndexChanged="rblTransportation_SelectedIndexChanged" >
<asp:ListItem Text="Unknown" Value="" />
<asp:ListItem Text="Yes" Value="True" />
<asp:ListItem Text="No" Value="False" />
</asp:RadioButtonList></td><td></td>
</tr>
<tr class="grouprow">
<td>Transportation Duration</td>
<td><asp:UpdatePanel ID="updTransportationHours" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="rblTransportation" EventName="selectedindexchanged" />
</Triggers>
<ContentTemplate>
<asp:TextBox ID="txtTransportationHours" runat="server" Text='<%# Bind("AdmissionTransportationHours")%>' CssClass="tinytextbox" />
<label class="unit">Hours</label>
<asp:RegularExpressionValidator ID="revTransportationHours" runat="server" ControlToValidate="txtTransportationHours" ValidationExpression="\d{1,3}(\.\d{1,2})?"
ValidationGroup="Past30Days" ErrorMessage="Invalid format for Transporation Duration. Please enter in format 'xxx.xx', e.g. '3.25'" Display="Dynamic"
CssClass="error" >*</asp:RegularExpressionValidator>
<asp:RangeValidator ID="rvTransportationDuration" runat="server" ControlToValidate="txtTransportationHours" CssClass="error" ValidationGroup="Past30Days" type="Double"
ErrorMessage="The Transportation Duration cannot be more than 100" MinimumValue="0" MaximumValue="100" >*</asp:RangeValidator>
</ContentTemplate>
</asp:UpdatePanel></td><td></td>
</tr>
I believe you need your rblTransportation RadioButtonList wrapped in an UpdatePanel as well.
Since that control isn't in an UpdatePanel, it causes a full postback.
The answer is gloriously simple, though I'm too tired to figure out why it works just now. I simply need to set ClientIDMode = AutoID on the RadioButtonLists and CheckBoxLists and they now trigger an asynchronous postback rather than a full one. They don't need to be within their own UpdatePanels either.
I got the answer from this SO question.
Can you try <asp:blablacontrol style="Display:none;"> </asp:control>
modalpanels has same problem and this codes solved my problem
Related
Working on an asp.net page I created a custom ajax web user control that displays the contents of a list value (which is loaded via database calls). The control includes "next" and "previous" buttons, as well as a couple text boxes. My initial version used a session variable (iterator) to keep track of where the user is while clicking the buttons and filling the text boxes with values from the List[].
In my next iteration, I need to be able to use this custom control, which will be presented many times in a table (or more probably grid), but I'm having trouble figuring out how to handle the iterator, since the session variable will obviously no longer work.
Does anyone have a suggested approach, or a recommended article?
I solved the problem by creating a second form on my user control that is segregated from the controls contained within the UpdatePanel. Before those controls are refreshed, the segregated control (a label in this case) is programmatically assigned a value and when the control Page_Load event fires it references the segregated label value to keep track of it's current position. I also had to move the ScriptManager out of my control and place it on the page(s) the control will be used on, since there will be several of these custom user controls on the page and only one ScriptManager is permitted per page.
<form id="NaviControl" >
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Panel ID="controlsPanel" runat="server" HorizontalAlign="Center" >
<asp:Panel ID="Panel1" runat="server" >
<asp:Button ID="btnLast" runat="server" Text="Previous" Height="25px" Width="75px" OnClick="btnLast_Click" />
<asp:TextBox ID="tbStatusCode" runat="server" ></asp:TextBox>
</asp:Panel>
<asp:Panel ID="Panel2" runat="server" HorizontalAlign="Center" >
<asp:TextBox ID="tbDescription" runat="server" ></asp:TextBox>
<asp:Button ID="btnNext" runat="server" Text="Next" Height="25px" Width="75px" OnClick="btnNext_Click" />
</asp:Panel>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
<form>
<asp:Label ID="lblCounter" runat="server" visible="false" />
</form>
Hope some other nubs find this approach useful.
For some reason, I can't get the validator to raise a flag when I do things wrong.
<asp:DropDownList ID="ddlTypeList" runat="server" DataSourceID="ods_TypeOptions" DataTextField="name" DataValueField="id" SelectedValue='<%# Bind("Type") %>' AppendDataBoundItems="true">
<asp:ListItem Text="-" Value="-1" Selected="True"></asp:ListItem>
</asp:DropDownList>
The drop down list has nice values, incl the initial dummy.
Neither
<asp:RequiredFieldValidator ID="rfw" runat="server" ControlToValidate="ddlTypeList"
InitialValue="-1" ToolTip="Required">*</asp:RequiredFieldValidator>
Nor
<asp:CompareValidator ID="cv" runat="server" ControlToValidate="ddlTypeList" ValueToCompare="-1" Operator="NotEqual" ToolTip="Required">*</asp:CompareValidator>
Raises any flags to say "hey - u messed up, go fix it". For all the google, searching, reviews, swinging big hammers, I have yet to spot what I am doing wrong.
I just want one solution to fix them all.
Oh yes, I also had a ValidationGroup="myGroup" between the DDL, RFV/CV and the button. No luck.
Your code is correct. You must have some element of code or markup that is obstructing the functionality of the validator. Is it possibly that the "-" item has its value changed from "-1" to something else?
Verify that your button that submits the form has CausesValidation=True.Also, make sure that the parent of the validators is not set to Visible=False or the children will not render on the page.
Verify that the RequiredFieldValidator and CompareValidator are rendering in the markup by searching for "_cv" or possibly "cv" in the outputted markup. If it is not there, then one of the parent elements is not being rendered or the validators are being deleted.
I have two update panels (lets call them A and B). In A, I have a simple checkbox. AutoPostback set to true. When you check it (or uncheck it), it will enable/disable a simple dropdown within the same UpdatePanel.
UpdatePanel B has a long running process in it. It fires off a request for a dropdown to be created that takes nearly 2 minutes to construct. If I load the page and don't touch anything, the dropdown is constructed after about 2 minutes and renders perfectly. However, if during that two minutes I decide to check my checkbox (and cause a partial postback for panel A), updatepanel B never gets rendered. While debugging, I found that it is completing its retrieval successfully, but the actual panel never refreshes to show the control.
I have tried using UpdateMode = Conditional on panel B (to ensure it would not be disturbed by panel A) and it produces the same results. I have verified that B.Update() is being called also.
EDIT
Panel A:
<asp:UpdatePanel ID="upMailScrub" runat="server">
<ContentTemplate>
<asp:Button ID="btnAnalyzeLaunch" runat="server" onclick="btnAnalyzeLaunch_Click" Text="Analyze Launch" style="display: none" />
<table>
<tr>
<td><asp:CheckBox ID="cbxScrub" runat="server" Checked="true"
oncheckedchanged="cbxScrub_CheckedChanged" AutoPostBack="True" /></td><td><label for="cbxScrub">Scrub this campaign</label></td>
<td style="padding-left: 10px">
Vendor: <asp:DropDownList ID="ddlScrubVendor" runat="server">
<asp:ListItem Text="LexisNexis" Value="LexisNexis" />
</asp:DropDownList>
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
Panel B:
<asp:UpdatePanel ID="upDdlCampaigns" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAnalyzeLaunch" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:HiddenField id="hidAction" runat="server" />
<asp:Panel ID="pnlPleaseWait" runat="server"><img src="style/images/PleaseWait.gif" /> Please wait while the Five9 Campaigns are retrieved...</asp:Panel>
<asp:DropDownList ID="ddlCampaigns" Visible="false" runat="server" class="required"
AutoPostBack="True" OnSelectedIndexChanged="ddlCampaigns_SelectedIndexChanged" />
<asp:Button ID="btnRefreshDDL" runat="server" onclick="btnRefreshDDL_Click" style="display: none" />
</ContentTemplate>
</asp:UpdatePanel>
Any suggestions? Thanks.
You ask too much from UpdatePanel :)
UpdatePanel can not work with 2 parallel request that way. Consider to make some ajax call to get your results.
Why you may ask, one basic reason is that every page have only one viewstate. When you ask from the A or the B, UpdatePanel to send/get data, then the viewstate must change to a new viewstate. Now, when you ask a result from A, and before you end, you ask results from B, you going to get 2 different viewstate, and one of them is going to fail because in the middle time have change.
ViewState is not the only think, in every update panel click, the page post back all inputs post to page, both A and B inputs and all the rest inside the page, this is also a problem. Imaging this for example, you trigger A UpdatePanel with inputs A+B, and then before the A ends, you trigger B UpdatePanel with the same inputs. Now A, waits for results from A+B, the same and B, but in the middle time the A+B results from A is now different because B has change them - and fails.
Basics:
I have a text box (txtDepositAmount) that people can
enter a deposit amount into and a
drop down (ddlSelectedTerm) that sets the terms.
Through these two values I calculate
the APY (lblCurrentApy).
Rules:
If only one of the values is selected I still want to do an update on the current APY label and clear it.
If either value changes I want to update the current APY and recalculate.
The problem:
As soon as I click away from the textbox and onto the drop down to select my term the drop down flashes and closes because the textbox TextChanged event was just fired.
I have to click on the drop down a second time to be able to select anything!
Do I need to change what event I'm looking at or do I need to move some of the controls outside of the UpdatePanel? Can this only happen if some of the business rules change? Should I just give up and go to javascript?
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table width="100%">
<tr>
<td align="left" style="width: 10%" class="LineAlign">
</td>
<td align="left" style="width: 40%" class="LineAlign">
<asp:Label ID="lblDollarSymbol" runat="server" Text="$"/>
<asp:TextBox ID="txtDepositAmount" runat="server"
AutoPostBack="true" TabIndex="1" MaxLength="14"
ontextchanged="txtDepositAmount_TextChanged"/>
</td>
<td align="left" style="width: 30%" class="LineAlign">
<asp:DropDownList ID="ddlSelectedTerm" runat="server"
AutoPostBack="true" TabIndex="2"
onselectedindexchanged="ddlSelectedTerm_SelectedIndexChanged">
</asp:DropDownList>
</td>
<td align="center" style="width: 20%">
<asp:Label ID="lblCurrentApy" runat="server"/>
<asp:Label ID="lblPercentSymbol" runat="server" Text="%"/>
</td>
</tr>
</table>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlSelectedTerm" />
<asp:AsyncPostBackTrigger ControlID="txtDepositAmount" />
</Triggers>
</asp:UpdatePanel>
autopostback="true" on your textbox is causing this, since both controls are reloaded after they leave the textbox. I doubt there is a way to avoid this as long as they are in the same UpdatePanel.
Maybe you could set focus to the dropdown list after the textbox-initiated postback, or you could probably make this work by putting the controls in separate UpdatePanels. But really it seems the wrong way to go about it. I would use javascript (and ajax if the logic is complicated) to update the APY. Or just add a "calculate" button...
(Edit)
Here's a slightly ugly hack to avoid ajax, three update panels and still be able to do your logic server side. I do not approve of this method but it is quick and dirty.
Put the Label control that contains the calculation results in an UpdatePanel. The input controls do not need to be in an UpdatePanel.
In the update panel (with the results) have a hidden submit button:
<asp:Button ID="DoCalculate" style="display:none;" UseSubmitBehavior="false"
runat="server" OnClick="Recalculate()" />
This should be the trigger for the UpdatePanel. Then have your two input controls click that button using javascript to cause a partial postback to the "results" panel. Here is the code to add this javascript for the dropdown, for example, in Page_Load:
ddSelectedTerm.Attributes.Add("onSelectedIndexChanged",
"document.getElementByID('" + DoCalculate.ClientID + "').Click()");
Then in put the C# code to do the calculation and update the label in the 2nd update panel in the "Recalculate()" method.
This should work, and give you better layout control and less code flow ugliness then using 3 update panels.
You can just use the Focus() in the server event. For example if you have txtBox1 and txtBox2 and want to have the focus in the box 2 after write something in box 1 and both of them inside an update panel.
Only go to the TextChange event of the box 1 and write txtBox2.Focus() and after the update of the panel the focus will be in the box 2. :)
Hope helps...
I ripped out the UpdatePanel and just did jquery. Screw Microsoft.
I have a question regarding a custom validator in my page. The custom validator is located inside an update panel and this update panel is inside another upadate panel. The OnServerValidate
fires and everything is fine. The problem is with ValidateEmptyText attribute. The error message is displayed as and when the user clicks on the text box and chooses some data from the
popup control. I wanted this to be in such a way that the server validate should validate the text entered and not before some text was entered. Could you please give me some
pointers regarding this?
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:TextBox ID="txt1" runat="server"></asp:TextBox>
<asp:CustomValidator ID="custValFromData" runat="server" Display="Dynamic" ControlToValidate="txtDate"
ErrorMessage="From month entered is invalid" OnServerValidate="custValFromData_Validate" ValidateEmptyText="true"></asp:CustomValidator>
<ajaxToolkit:PopupControlExtender runat="server" TargetControlID="txtDate" />
</ContentTemplate>
</asp:UpdatePanel>
</ContentTemplate>
</asp:UpdatePanel>
It would be of great help if somebody could help me in understanding the issue and finding a solution. Thanks in advance!
Regards,
Karthik
Never mind, I solved this problem. I removed ValidateEmptyText, used a RequiredValidator and set EnableClientValidation to false for both and that solved the problem.
Thanks!