Having a strange issue with the TabContainer in the AJAX Toolkit.
We have several views into a customer record system that we have built as ASP.net controls. These controls use UpdatePanels to load data asynchronously. We use jQuery and jquery.ui to place these controls in separate tabs on a single page.
Which all works swimmingly.
Lately, I've gotten a little tired of the jQuery tab hackish approach and decided to port everything to use the TabContainer. I want to be able to control the tabs as objects.
At first glance, everything works perfectly. I just slapped the controls into tabs in a TabContainer and everything looked great. However, for some reason, databound controls are losing their data.
For instance, grid views vanish when I switch pages. A drop down control with an OnTextChanged event, loses its databound list of values upon post back.
Something about the TabContainer -> Custom Control -> UpdatePanel -> Control that uses data binding heirarchy is throwing it out of whack and the debugger isn't shedding any light. It seems like control state isn't being stored.
I don't really know enough about control state to know what to look for.
Any ideas? Here is the markup for the TabContainer:
<asp:TabContainer ID="tcBanner" runat="server" ActiveTabIndex="0" Width="100%"
EnableViewState="False" ScrollBars="Vertical">
<asp:TabPanel runat="server" HeaderText="Comments" ID="tbComments">
<ContentTemplate>
<luBannerControl:Comments ID="commentsTabContent" runat="server" />
</ContentTemplate>
</asp:TabPanel>
<asp:TabPanel runat="server" HeaderText="General" ID="tbContact">
<ContentTemplate>
<luBannerControl:Contact ID="contactTabContent" runat="server" />
</ContentTemplate>
</asp:TabPanel>
</asp:TabContainer>
Here is the markup for one of the controls:
<asp:UpdatePanel ID="pnlComments" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:GridView ID="CommentsGridView" AllowPaging="true" PageSize="20" DataSourceID="BannerSqlDataSource" runat="server" AutoGenerateColumns="False" GridLines="None" CssClass="CommentGrid" HeaderStyle-CssClass="CommentGridHeader" RowStyle-CssClass="CommentRowsEven" AlternatingRowStyle-CssClass="CommentRowsOdd">
<Columns>
<asp:BoundField DataField="SPRCMNT_TEXT" HeaderText="Comment" SortExpression="SPRCMNT_TEXT" />
<asp:BoundField DataField="SPRCMNT_DATE" HeaderText="Created" SortExpression="SPRCMNT_DATE" DataFormatString="{0:M/dd/yyyy}" />
<asp:BoundField DataField="SPRCMNT_CMTT_CODE" HeaderText="Type" SortExpression="SPRCMNT_CMTT_CODE" />
<asp:BoundField DataField="SPRCMNT_CTYP_CODE" HeaderText="Source" SortExpression="SPRCMNT_CTYP_CODE" />
<asp:BoundField DataField="sprcmnt_user_id" HeaderText="User" SortExpression="sprcmnt_user_id" />
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="txtSearch" EventName="TextChanged" />
<asp:AsyncPostBackTrigger ControlID="btnClearFilter" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
This ended up being completely unrelated to nested TabContainers.
I had unknowingly broken the controls in question before adding them to the TabContainer and surprisingly, this meant they did not function the way they used to.
Sorry for wasting your collective time.
Thanks,
Clif
Make sure your TabContainer's OnDemand Property is turned off. I know for a fact that this can cause your controls such as GridView to lose their data while retain their rows, especially if you dynamically generate your controls.
Via Markup:
<asp:TabContainer ID="tcBanner" runat="server" ActiveTabIndex="0" Width="100%"
EnableViewState="False" ScrollBars="Vertical" OnDemand="false" >
Via code:
tcBanner.OnDemand = false;
Related
I have a gridview with some textboxes and buttons inside the gridview. I want to use updatepanels when the buttons are clicked so that only one textbox is refreshed instead of the whole page. I tried to add my ScriptManager and UpdatePanel inside my gridview but I get errors saying the tags aren't recognized.
I've looked elsewhere on SO for solutions and others have said to place the whole gridview in an UpdatePanel. However, I don't want the whole grid to be updated (it's pretty lengthy). Is it possible to have individual UpdatePanels in my gridview?
EDIT:
Here is some code to go along with my question:
<asp:UpdatePanel ID="UpdatePanel" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="PCalendar" EventName="SelectedChange" />
</Triggers>
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField HeaderText="QS">
<ItemTemplate>
<asp:TextBox ID="TextBox" runat="server" Text=' <%#Bind("PDate") %>' OnTextChanged="SetTextBox" AutoPostBack="True"></asp:TextBox>
<asp:ImageButton ID="PButton" runat="server" OnClick="ShowCalendar" ImageUrl="../images/calendarIcon.jpg" />
<asp:Calendar ID="PCalendar" runat="server" Visible="false" OnSelectionChanged="SetDate" ></asp:Calendar>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
Here is what it's going to sorta look like. Once you post your code, it will be easier to see how close you are and how to help you properly. But this is the general idea.
<asp:UpdatePanel ID="UpdatePanel" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="buttonOneID" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="buttonTwoID" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server">
<Columns>
//columns code here
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
I have two UpdatePanel in a single asp.net page.One has a submit button and a progress bar , on click on this button there is a process which fetch the data from a XML file and stores in Database.
Second update panel is used to display the content from a log about the progress of the data insertion from XML and it is updated using a timer control.
Now the problem is that when a request is submitted from first panel , second panel stop updating the content.
Should I try any other library or some sort of jq metohods to update page.
thanx in advance
here is my code,...
<asp:scriptmanager runat="server" ID="scrpManager"> </asp:scriptmanager>
<asp:UpdatePanel ID="updLeft" runat ="server">
<ContentTemplate>
<asp:Button ID="Submit" runat="server" onclick="Submit_Click"
Text="Process" />
</ContentTemplate>
<Triggers >
<asp:AsyncPostBackTrigger ControlID ="Button3" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<asp:UpdateProgress runat="server" AssociatedUpdatePanelID="updLeft"
ID="UpdateProgress21">
<ProgressTemplate>
<div class="loadingbox">
<img src="spinner.gif" align="absmiddle" />
<asp:Label ID="lblProgress21" runat="server">Please wait while processing...</asp:Label>
</div>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="updPnlRight" runat ="server" >
<ContentTemplate >
<asp:Timer Interval="1000" ID="timer1" runat="server" ontick="timer1_Tick" ></asp:Timer>
<asp:GridView ID="GridView1" ShowHeader ="false" AutoGenerateColumns ="false" runat="server">
<Columns >
<asp:BoundField DataField ="status_MSG" HeaderText ="" />
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers >
<ajax:AsyncPostBackTrigger ControlID ="timer1" EventName="Tick" />
</Triggers>
</ajax:UpdatePanel>
protected void Submit_Click(object sender, EventArgs e)
{
//Do insertion process , takes 30 minutes,
}
I've had nothing but misery with update panels. I urge you to use an alternative such as client side templates. Knockout.js and Angular.js are probably good places to start.
If you paste your code, or a (non) working example of your issue, I'll try offer a fix.
I'm trying to be slick and I'm putting this user control in a div that covers the whole page.
However when I click on the search button I get a full postback.
Any ideas on how to get it to not postback and just update the gridview?
And just to be clear. The following control is in a ascx file. Which is called in a aspx page.
<%# Control Language="C#" AutoEventWireup="true" CodeFile="PropertyViewAddEntity.ascx.cs"
Inherits="UserControls_PropertyViewAddEntity" %>
<p>Search for State City County zip</p>
<asp:Panel ID="Panel1" runat="server" DefaultButton="Button2ae">
<p>
<asp:TextBox ID="TextBox1ae" runat="server" Width="500px"></asp:TextBox>
<asp:Button ID="Button2ae" runat="server" Text="Search" CausesValidation="false" />
</p>
</asp:Panel>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="GridView2ae" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource3ae"
OnSelectedIndexChanged="GridView2ae_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="zipcodeid" HeaderText="zipcodeid" SortExpression="zipcodeid" />
<asp:BoundField DataField="zip_code" HeaderText="zip_code" SortExpression="zip_code" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
<asp:BoundField DataField="city_alias_name" HeaderText="city_alias_name" SortExpression="city_alias_name" />
<asp:BoundField DataField="county_name" HeaderText="county_name" SortExpression="county_name" />
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button2ae" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
btw the control is in a placeholder
<asp:PlaceHolder ID="ControlContainer" runat="server"/>
and called from the code behind.
Control mycontrol = LoadControl("~/UserControls/PropertyViewAddEntity.ascx");
ControlContainer.Controls.Add(mycontrol);
I have finally figured out the issue.
In order for things to work properly adding the user control via codebehind will not work!
To get things working properly you must declare the usercontrol on the page so that you can access the UpdateMode="Conditional" property of the usercontrol.
<%# Register TagPrefix="my" TagName="AddEntity" Src="~/UserControls/PropertyViewAddEntity.ascx" %>
<my:AddEntity Visible="false" ID="test1" runat="server" ClientIDMode="Inherit" UpdateMode="Conditional" />
I set the Visible property of the control to false so that I can show it via button click.
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
And in the code behind I did this.
protected void Button1_Click(object sender, EventArgs e)
{
test1.Visible = true;
}
Once the updatemode is set. Everything works as it should.
I have this code in my aspx page:
<form id="form2" runat="server">
<asp:ScriptManager ID="ItemsScriptManager" runat="server" EnablePartialRendering="true" />
<asp:Button runat="server" ID="SearchButton" OnClick="ItemsSearch" Text="Search" />
<asp:UpdatePanel runat="server" ID="ItemsUpdatePanel">
<ContentTemplate>
<asp:ObjectDataSource runat="server" ID="ItemsDS"
TypeName="TemplateGridViewODSPagingSorting.ItemDAO" SelectMethod="GetItems" />
<asp:GridView runat="server" ID="ItemsGridView" DataSourceID="ItemsDS"
AllowPaging="true" AllowSorting="true" PageSize="4">
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</form>
By pressing on another page of the GridView the Page_Load is triggered, is this normal behavior for a partial postback?
Partial rendering using UpdatePanel does not change or affect the whole Page life cycle in ASP.NET.
it's a small trick used to re-render only a certain region of the page in the browser (the UpdatePanel) but nothing else change, so yes, it's normal to see Page_Load and all other events to be triggered as usual; it has to be like that or it would not work :)
Yes, the during update panel update, the page_load will be called with every asynchronous postback to the server, to overcome this, you can use jquery ajax.
In doing some reworking of my web application I encountered the following issue:
Although an ASP UpdatePanel does not have a height property it does not automatically expand to fill its parents container. Instead, it grows with its children's dimensions. In my scenario, the child does not have dimensions -- it should expand to fill its parents container. This causes both the UpdatePanel and its child to have very small heights.
Before I had:
[Parent Container] -> [Child Container] with both ParentContainer and ChildContainer's height property unset so that they will fill containers higher up in the hierarchy.
Now I have:
[Parent Container] -> [Update Panel] -> [Child Container]. Parent Container's dimensions are not guaranteed to be non-empty, so I am unable to programatically set ChildContainer's dimensions in all cases. As such, I would like my UpdatePanel to work in the same fashion as the controls it is wrapped around.
Is my best bet to go into the CSS and do something like:
.UpdatePanel
{
height: 100%;
}
or do I have other, cleaner options available to me? I am creating these controls server-side, so I don't have the opportunity to wrap them in divs (nor do I want to).
EDIT:
I (can't?) use Panel instead of UpdatePanel because I would like to use the functionality of being able to update conditionally. I have a timer on my page which calls UpdatePanel.Update() on controls -- this functionality does not exist in panel AFAIK.
The body of my page is height: 100% and here is the static structure hierarchy.
The location where RadPane2 is declared is where an UpdatePanel will be slipped in. It needs to be between the RadPane and the CormantRadDockZone controls. This is only the 'base' implementation, however. Users have the ability to stack more RadPane/UpdatePanel/CormantRadDockZone 1:1:1 contents onto the page. As such, I have UpdatePanels being generated dynamically -- which means I can't apply the CSS to just an UpdatePanel's ID.
<telerik:RadSplitter ID="RadSplitter2" runat="server" BorderSize="0" Height="100%" HeightOffset="155" Skin="Web20" Width="100%" PanesBorderSize="0">
<telerik:RadPane ID="RadPane_DefaultExpand" runat="server" CssClass="allRoundedCorners" Scrolling="None">
<telerik:RadMultiPage ID="RadMultiPage1" Runat="server" SelectedIndex="0">
<telerik:RadPageView ID="RadPageView1" runat="server">
<telerik:RadSplitter ID="RadSplitter1" Runat="server" BorderSize="0" Height="100%" Skin="Web20" Width="100%">
<telerik:RadPane ID="RadPane1" Runat="server" CssClass="leftRoundedCorners" Scrolling="None" Width="20px">
<telerik:RadSlidingZone ID="RadSlidingZone1" Runat="server" ClickToOpen="True" Width="20px">
<telerik:RadSlidingPane ID="RadSlidingPane1" Runat="server" BackColor="#ECF4FD" IconUrl="~/Content/Dashboard/Icons/configuration.png" MinWidth="160" Scrolling="Y" TabView="ImageOnly" Title="Configuration" Width="160px" EnableDock="False">
<telerik:RadListBox ID="lstBxSettings" runat="server" EnableDragAndDrop="True" onclientdragging="OnClientDragging" ondropped="LstBxSettings_Dropped" Skin="Web20" Width="100%" onclientdropped="OnClientDropped">
<Items>
<telerik:RadListBoxItem Text="Horizontal Bar" Value="Horizontal"/>
<telerik:RadListBoxItem Text="Vertical Bar" Value="Vertical" />
</Items>
</telerik:RadListBox>
</telerik:RadSlidingPane>
<telerik:RadSlidingPane ID="RadSlidingPane2" Runat="server" IconUrl="~/Content/Dashboard/Icons/chart.png" TabView="ImageOnly" BackColor="#ECF4FD" MinWidth="160" Scrolling="Y" Title="Custom Widgets" Width="160px" EnableDock="False">
<telerik:RadListBox ID="lstBxCustom" runat="server" EnableDragAndDrop="True" onclientdragging="OnClientDragging" onclientdropped="OnClientDropped" ondropped="RadListBox_Dropped" Skin="Web20" Sort="Ascending" Width="100%" />
</telerik:RadSlidingPane>
<telerik:RadSlidingPane ID="RadSlidingPane3" Runat="server" BackColor="#ECF4FD" IconUrl="~/Content/Dashboard/Icons/historical.png" MinWidth="160" Scrolling="Y" TabView="ImageOnly" Title="Historical Widgets" Width="160px" EnableDock="False">
<telerik:RadListBox ID="lstBxHistorical" runat="server" EnableDragAndDrop="True" onclientdragging="OnClientDragging" onclientdropped="OnClientDropped" ondropped="RadListBox_Dropped" Skin="Web20" Sort="Ascending" Width="100%" />
</telerik:RadSlidingPane>
<telerik:RadSlidingPane ID="RadSlidingPane4" Runat="server" IconUrl="~/Content/Dashboard/Icons/settings_global.png" onclientbeforeexpand="ShowDashboardGlobalSettings" TabView="ImageOnly" EnableDock="False" />
</telerik:RadSlidingZone>
</telerik:RadPane>
<telerik:RadPane ID="RadPane2" Runat="server" BackColor="White" BorderColor="White" CssClass="rightRoundedCorners" Scrolling="None" onclientresized="OnClientResized">
<cc1:CormantRadDockZone ID="RadDockZone1" runat="server" />
</telerik:RadPane>
</telerik:RadSplitter>
</telerik:RadPageView>
</telerik:RadMultiPage>
</telerik:RadPane>
</telerik:RadSplitter>
UpdatePanel will translate to a div or span on client side so as long as you set the css class properly, this should work. Going via CSS is the cleanest approach.
Here's how you can set the css class (if you want to use this in a css file, make sure you've PerformSubstitution set to true):
#<%=UpdatePanel1.ClientID%> {
height: 100;
}
Also, based on browser type, you may have to reset margin and padding to 0.
Make sure that the UpdatePanel's parent has height set too.
Update: use a Panel to wrap UpdatePanel (not substitute it)
<asp:Panel ID="Panel1" runat="Server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
</asp:UpdatePanel>
</asp:Panel>
Noticed RadPane has a CssClass property so you can just add it there.
<telerik:RadPane ID="RadPane2" Runat="server" BackColor="White" BorderColor="White" CssClass="rightRoundedCorners myCssClass" Scrolling="None" onclientresized="OnClientResized">
<cc1:CormantRadDockZone ID="RadDockZone1" runat="server" />
</telerik:RadPane>