asp:UpdatePanel on individual RadGrid rows - asp.net

I am making some changes to an internal application that has a Telerik RadGrid component on one .aspx page.
Each row in the RadGrid represents an order and there is a dropdown which allows setting the status of the order. Changing the status of the order updates a couple of other properties of the order which are displayed on that row.
Up until now, changing the order status has resulted in a complete page post back and re-render. I'm keen to change this to a partial post back using an UpdatePanel. I could wrap the status dropdown (a RadCombo) in an UpdatePanel which would take care of the actual database changes that are required (as per the code sample below), but then without updating the other properties on the RadGrid row, the updates are not presented to the user.
<telerik:RadGrid ID="OrdersGrid" runat="server" ...>
<MasterTableView DataKeyNames="OrderId" AllowMultiColumnSorting="false">
<NoRecordsTemplate ...></NoRecordsTemplate>
<Columns>
<telerik:GridBoundColumn ... />
...
<telerik:GridTemplateColumn HeaderText="Order Status" UniqueName="OrderStatus">
<ItemTemplate>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<telerik:RadComboBox ID="RadOrderStatus" DataSourceID="OrderStatusDataSource" runat="server"
SelectedValue='<%# Bind("OrderStatus") %>' Skin="Metro" Width="180px" DataTextField="OrderStatus"
DataValueField="OrderStatus" AutoPostBack="True" EnableLoadOnDemand="False" OnSelectedIndexChanged="RadOrderStatus_SelectedIndexChanged">
</telerik:RadComboBox>
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</telerik:GridTemplateColumn>
</Columns>
<SortExpressions>...</SortExpressions>
</MasterTableView>
</telerik:RadGrid>
I'm wondering how I can use the UpdatePanel to effectively wrap the row of the RadGrid so that the entire row can be updated as opposed to just the cell that the dropdown is in. I've tried experimenting already with tag placement but I'm new to Telerik and therefore not very clued up.
At what level in the mark up can I place the UpdatePanel to get this to work as I'd like?
Or is there a Telerik way of doing this?
I could wrap the whole grid but if possible, I'd rather not have the whole grid update on each partial post back, the permitted operations are limited to the row level so I see a full grid update as wasteful.

You can't place an UpdatePanel around each row. For starters, there is no provision to do that (you can't do it with the standard GridView either). Then, if you manage to do that (e.g., override the Render event), you would get invalid markup because you can't have <div> elements inside the <table> and between the other <tr> nodes.
One note on the performance—the AJAX request will have the page go through its entire lifecycle on the server, so all code will be executed again and any time consuming operation will also be executed. The only difference between the AJAX and the full postback is what gets rendered and returned in the response, so you basically shave off network time only.
What you can do is the following:
wrap the entire grid. I would use RadAjaxPanel and RadAjaxLoadingPanel so you have a pretty loading indicator. Something like:
<telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" Skin="Black"></telerik:RadAjaxLoadingPanel>
<telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server" LoadingPanelID="RadAjaxLoadingPanel1">
<telerik:RadGrid ID="RadGrid1" runat="server"></telerik:RadGrid>
</telerik:RadAjaxPanel>
OR, use client-side code and jQuery. The combo can call a WebService or a PageMethod that will return the data and you can use jQuery to traverse the DOM and update the other elements (textboxes, dropdowns, whatever you have). This is going to be more difficult.

Related

User control retains focus incorrectly after TextChanged postback when UC is contained within a detailsview control

I reference a previous post: Focus lost on partial postback with UserControls inside UpdatePanel
where an excellent solution works perfectly for web-page controls within a form.
However, I have placed my UC inside a detailsview template-field (for Edit+Insert).
The UC contains an UpdatePanel needed to adjust the text-formatting and control's style(s) following the TextChanged event of the UC-textbox (AutoPostback=True) during the Edit-mode and Insert-modes of the DetailsView.
As such, when the DetailsView-control is in Edit-mode, and user changes Text in the UC, the textchanged event is fired and the user-entered value is validated and when OK, the thousounds-separator (comma) are added to the UC-textbox-text, BUT, the focus moves to the next field in the DetailsView and QUICKLY returns back to the UC-control.
This incorrect focus-move(s) does NOT occur when the UC is wrapped in updatepanels as noted in the referenced post since the focus and tabbing order works perfectly outside of the DetailsView control.
Here is the aspx markup for the template-field-EDIT (only).
<asp:TemplateField HeaderText="Initial Mileage" SortExpression="IMilage">
<EditItemTemplate>
<asp:UpdatePanel ID="updpnlIMilage" runat="server" UpdateMode="Conditional" >
<ContentTemplate>
<TGANumeric:GANumeric ID="ucnumIMileage" runat="server"
Caption="Initial Mileage" HideCaption="True" Width="160"
DisplayMask="999,999" InputMask="999999"
Enabled="True" IsRequired="False"
MinNumber="0" MaxNumber="999999"
Text='<%# Bind("IMilage") %>'
TabIndex="0"
/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ucnumIMileage" />
</Triggers>
</asp:UpdatePanel>
</EditItemTemplate>
Thanks in advance. Your comments are welcome.
Thanks...J.
So are you saying your control hierearchy (partial) is:
UpdatePanel > TGANumeric:GANumeric > UpdatePanel > TextBox
This is an awful lot of overhead to just format a number with a comma, which is the only reason I see for your posting back. As far as I can tell there is nothing you need from the server, so why post?
Or is there?
My thoughts, lose the update panels, disable the AutoPostback on the Textbox, handle the formatting client side if it must be seen immediately, or leave the formatting to the DetailsView field DataStringFormat when it posts after save.
I'm betting this will clear up any focus issues.
Based on all the comments in this thread, I want to explain the actual root cause of the tabbing misbehavior.
1) There were no coding issues or event-issues with the user-control.
2) There were no coding issues or event-issues with the layering of Master-page, Content-page, Ajax update-panels / nested update-panels, details-view and template-fields containing the user-control.
3) The real culprit was a small snippet of code where the page adjusts the web-controls on the form based on the "state" (status) of the page/form. I manage the adjusting of visible and/or enabling of web-controls in a single subroutine in the code-behind so that all of this enabling/disabling visible/not-visible occurs in one place under a set of CASE-statements.
The actual erroneous snippet of code inside the 'sbSetFormState()'-method was messing with the class-variable 'm_eFormState' that actually caused the update panel to re-fire and thus the tabbing got thrown out of sequence.
This was discovered by the great suggestion from 'fnostro' to remove or add functionality features until the mis-behavior exposes itself.
I mark this topic as resolved/closed.
Again, thanks to fnostro !!!

Nested UpdatePanel causes parent to postback?

I'm under the impression that a control in a nested UpdatePanel will cause the top level UpdatePanel to refresh (thus refreshing both UpdatePanels) because any events on that control act as an "implicit" trigger. Is that correct?
I've been trying to wire something like this up-
UserControl
Parent UpdatePanel
"Show" button
ASP:Panel
Dynamically added UserControls, each with UpdatePanels
When the Show button is clicked, the ASP:Panel becomes visible and starts adding UserControls to itself dynamically, based on some back-end logic.
Each of the dynamically added controls (henceforth: UserControls) have their own Atlas-enabled buttons and links, so they have UpdatePanels too. Currently when I click on a link in one of the UserControls, the entire contents of the ASP:Panel disappear, as if it's being re-rendered. All of my dynamically-added controls disappear, and none of their click events are caught in the debugger.
I'm assuming what's happening here is that controls that reside in nested update panels are causing the parent UpdatePanel to post back because they're firing "implicit" triggers. Is there a way for my UserControls to operate autonomously and not mess with the ASP:Panel that contains them?
If not, what strategy should I be pursuing here? If I have to re-render the entire ASP:Panel every time an event happens on one of the (possibly many) UserControls, that means I'll have to recreate the UserControls, which take a bit of effort to create. I'll also have to preserve some kind of view state to recreate them. I'm somewhat new to ASP.NET and that sounds intimidating. I'd rather never refresh the top leve UserControl and ASP:Panel if I can avoid it, and let each of the dynamically-added UserControls fire and handle their own events asynchronously.
EDIT: Instead of adding the controls dynamically, I added them to the markup(not a bad solution). So got rid of the controls disappearing problem, because now the controls are not added dynamically but instead exist in the markup. But still the parent UpdatePanel posting is a big performance hit, because all the UserControls are getting posted instead of one. How do I make only one UserControl postback? Also, I would like to know how to get rid of the problem of controls disappearing if added dynamically?
First off, keep in mind: UpdatePanels do not alter the lifecycle of a page.
All of the Control Tree (including the UpdatePanels) must be reconstructed just as with a Normal Postback Life-cycle.1 2 The UpdatePanels ensure that only a portion of the rendered (HTML) view is returned. Removing all UpdatePanels should result in the same behavior, except with a full postback. For instance, only the HTML representing a nested UpdatePanel (presumably because data changed) might be sent back in the XHR response.
To get "true" AJAX consider Page Methods. Alternatively, DevExpress (and perhaps Telerik and others?) offer their own form of "Callback Panels", which are similar to UpdatePanels, but can bypass parts of the life-cycle (and, as a result often do not support the ViewState model entirely or may introduce their own quirks).
While not understanding the above is the most likely reason for the controls "disappearing", here is my rule: Do Not Let [Nested] UpdatePanels Work "Automatically".
Edge cases with dynamic controls and nested UpdatePanels will be encountered. There might be a nice way to handle this, but I have failed on multiple different attempts.
Instead, for every update panel, run with:
UpdateMode="Conditional"
ChildrenAsTriggers="False"
With the "Conditional" UpdateMode, make sure to manually specify the Trigger control or call panel.Update() (although this hard-wires the Control) as required. Depending on needs ChildrenAsTriggers="True" might work as well. The big thing is that UpdateMode is not "Always" which is the default.
After switching to this approach, I have no problem -- well, almost none -- with nested UpdatePanels.
Happy coding!
1 If the page doesn't render correctly where Partial Rendering (in the ScriptManager) is disabled (e.g. all requests are full postbacks) then there is no reason to expect/believe it will work correctly with UpdatePanels.
2 There are times when it's warranted to "cheat" expensive recomputations in the control tree for controls that will not be re-rendered. However, I would consider these advanced cases that should only be done when performance analysis indicates there is a specific need.
I had a similar issue with a heavy ajax Gridview control, and a HTML page with multiple UpdatePanels, some nested, some not.
It took me over 3 weeks of trial and error, reading, testing, debugging and prototyping to finally resolve all the post backs and partial postbacks.
However I did notice a pattern, which worked for me.
Like the #user above's response, make sure your UpdatePanels are set Conditional and only specificy asp:PostBackTrigger on the final or decisive control that you want the page to do a full postback on. I always use asp:AsyncPostBackTrigger where ever possible.
So for example, if you're using UpdatePanels inside a GridView and you want a popup inside a cell of the gridview's row, then you need to use a nested UpdatePanel.
ie
<asp:TemplateField HeaderText="Actions & Communications">
<ItemTemplate>
<asp:UpdatePanel ID="upAction1" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnActionOK" />
</Triggers>
<ContentTemplate>
...
...
<ajaxToolkit:ModalPopupExtender ID="ajaxMPE" runat="server"
BackgroundCssClass="modalBackground"
PopupControlID="upAction2"
TargetControlID="btnADDaction">
</ajaxToolkit:ModalPopupExtender>
<asp:UpdatePanel ID="upAction2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="pnlACTION" runat="server" CssClass="pnlACTION">
<div id="divHDR">
<asp:Label ID="lblActionHdr" runat="server">** header **</asp:Label>
</div>
<div id="divBOD">
<table style="width: 98%; text-align:left">
<tr>
<td colspan="2">
Please enter action item:<br />
<asp:TextBox ID="txtAction" runat="server" ValidationGroup="vgAction" TextMode="MultiLine" Rows="3" Width="98%"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvAction" runat="server" ControlToValidate="txtAction" ValidationGroup="vgAction"
ErrorMessage="* Required" SetFocusOnError="True"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td colspan="2">
Select staff assigned to this task:<br />
<asp:DropDownList ID="ddlActionStaff" runat="server" AppendDataBoundItems="true" ValidationGroup="vgAction" />
<asp:RequiredFieldValidator ID="rfvStaff" runat="server" ControlToValidate="ddlActionStaff" InitialValue="0" ValidationGroup="vgAction"
ErrorMessage="* Required" SetFocusOnError="True" Width="98%"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<asp:Button ID="btnActionOK" runat="server" Text="OK" OnClick="btnActionOK_Click" ValidationGroup="vgAction" CausesValidation="false" />
<asp:Button ID="btnActionCANCEL" runat="server" Text="CANCEL" OnClick="btnActionCANCEL_Click" ValidationGroup="vgAction" CausesValidation="false" />
</td>
</tr>
</table>
</div>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
<asp:SqlDataSource ID="sdsTETactions" runat="server" ConnectionString="<%$ ConnectionStrings:ATCNTV1ConnectionString %>"
...
...
</asp:SqlDataSource>
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
Notice a few things here:
The ModalPopupExtender does not refer to the Ok and Cancel buttons. This is because I want them to trigger a partial postback to the server (code-behind)
The nested UpdatePanel (upAction2) is purely to force a partial postback on that panel only (pnlAction)! Therefore this forces the data validation triggers to work and keep the panel open if the user does not provide data in the requiredfield validators
The main UpdatePanel (upAction1) controls the entire lot and keeps all postbacks held within that panel only and NOT affecting the gridview (not shown entirely).
There is a great article here, which explains it better.
I hope this helps someone

DevExpress Hidden GridView CSS Issues

I have a repeater control that repeats a DevExpress ASPxGridView for every item bound to the repeater. The repeater is contained within an update panel. Events on the page, outside of the UpdatePanel, trigger the UpdatePanel (and subsequently the repeater) to update. All works fine if records are present to bind to the repeater. The repeater renders a grid for each record and all styles look perfect.
If the page initially loads and there are no items to display in the repeater, no grids are rendered (works as intended up until this point). If a record is eventually added and the repeater rebinds (because of the triggered UpdatePanel), the grid styles don't display. If the entire page is refreshed, the grid's styles display perfectly. Keep in mind that I'm using one of the default styles that comes with the grid, so these are being pulled from an AXD and not included in my MasterPage.
A bit too much code to post, but the nuts of the markup looks similar to this:
<asp:UpdatePanel ID="the UpdatePanelInQuestion" runat="server" UpdateMode="Conditional">
<asp:Repeater ID="theRepeaterInQuestion" runat="server" OnItemDataBound="theMethodThatHandlesGridPopulation">
<ItemTemplate>
<dxwgv:ASPxGridView ID="theGridViewInQuestion" runat="server" EnableViewState="false">
<Columns>
...
</Columns>
</ItemTemplate>
</asp:Repeater>
</asp:UpdatePanel>
Any ideas on how to make the styles of the grid display correctly without:
1) Refreshing the entire page instead of triggering.
2) Placing another empty grid on the page with style="display: none;" to force the styles to download.
This problem is caused by the fact that the required scripts for the DX ASP.NET controls are not registered on the page initially. It is possible to register them explicitely via the DevExpress.Web.ASPxClasses.ASPxWebControl.RegisterBaseScript method.
Please check the http://www.devexpress.com/issue=B191046 Support Center ticket regarding this.

Checkbox in GridView not persistent ASP.NET

I am having issues with this GridView. I update it in design mode, and the update does not make it to the code behind section. For example, I add field "xyz". Gridview says "xyz" fields exist in design mode. In code-behind, it does not exist. when you view the page in browser, ofcoure "xyz" field is not shown. After refresh, even the gridview looses this field in design mode. So ok I got around this problem and managed to add a template field which is now working.
Now the problem is, the checkbox that I added in one of the column is not persistent. I have a button which works on the selected values of checkboxes but each time I click the button, the page refereshes and all the checked values are lost (checked values becomes unchecked).
Does anyone has any idea?
Want to mention, I am working with a bit messy code. But dont want to change a lot at this time.
<asp:TemplateField HeaderText="All" >
<HeaderTemplate>
<asp:CheckBox ID="chkAll" runat="server" name="chkAll" />
</HeaderTemplate>
<EditItemTemplate>
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkRow" runat="server" />
</ItemTemplate>
</asp:TemplateField>
This took me a couple of days to figure out myself. Since my code was quite messy, it was hard to troubleshoot.
I put in some code in page_load default event that finally fixed. Don't know if I was putting code in the wrong place first. It definitely took some time though.

Delete from grid asp.net

i have this template field inside a gridview.
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="ImageButton2" ImageUrl="~/images/DeleteRecord.gif" runat="server"
OnClientClick="return ConfirmacionBorrarClausula();" CommandName="BorrarClausula" CommandArgument='<%#Eval("ClausulaID")%>' OnCommand="gvClausulas_OnRowDeleting" CausesValidation="false"
</ItemTemplate>
</asp:TemplateField>
I have another one in the same page but in a different gridview, almost exactly like this one but the second one isn´t working.
So i have two gridviews each one with a template field like the one here, one onRowDeleting working perfectly, the other one not working at all, when i click it, it asks for confirmation (javascript function) but when i click ok to delete, the grid loses it data and the page fires all the validators.
Thank you for your time.
Make sure the control IDs are set right. And Ispostback the control level set to true. And also Try deleting the control and add it again some time that might help. Try add it from design view.
i manage to solve it, the problem was the second gridview was losing its data on the pageload, i managed that but only with the first gridview.

Resources