Hi,
I have a WebTab control and add dynamically some tabs. Only first tab has content on initial stage, another tabs are empty. It is possible to load content on TabChanging with Ajax (without LoadOnDemandUrl and iframes) ?
Hi pobo001,
Nikolay gave you an example to add tab on client, which content has url. If you are interested in explicit child controls in tab items created by server, then it is supported as well. However, in this case, if you expect persistance of viewstate and server events for your dynamic controls, then you should follow general asp.net rules (that is not related to WebTab, but to any container).Those rules are quite simple:1. Recreate exactly same controls in every single session (postback).2. Use exactly the same unique values for IDs of your child controls.
You may add new tab item on server (using any server event) or on client (using any client event).If you need to add new tabs and controls using AJAX, then you should wrap WebTab into UpdatePanel.Note: the Async option in AutoPostBackFlags can not be used, because it affects only WebTab by itself, but not templates/content of its tab items.
For simplicity, I wrote a sample, which adds new tabs on client using AddNewTabItem and fills those tabs by dynamic controls in 2 ways: UserControlUrl and explicit new controls. ViewStates of those dynamic controls will persist.
aspx:
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <ig:WebTab ID="WebTab1" runat="server" Width="300px" Height="200px"> <Tabs> <ig:ContentTabItem runat="server" Text="Tab 1"> <Template> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> </Template> </ig:ContentTabItem> </Tabs> <AutoPostBackFlags SelectedIndexChanged="On" /> <AddNewTabItem Enabled="True"></AddNewTabItem> </ig:WebTab> </ContentTemplate></asp:UpdatePanel>
aspx.cs:
protected void Page_Load(object sender, EventArgs e){ int count = this.WebTab1.Tabs.Count; // skip 1st tab which was created in aspx while (count-- > 1) { ContentTabItem tab = this.WebTab1.Tabs[count]; if (count == 1) // note: that assignment can be used only once, because, UserControlUrl persists by itself tab.UserControlUrl = "WebUserControl1.ascx"; if (count == 2) { TextBox tb = new TextBox(); tb.ID = "TextBoxOn3rdTab"; tab.Controls.Add(tb); } // etc. }
}
Hi Viktor,
thank you for your answer. I don't need to add any Tabs on client side or using AJAX, all tabs are dynamically created (not in design mode) on first request. But they have no content, they are empty after first page load, besause the content of every tab is very heavy. What I need is a LoadOnDemand functionality, but without setting ContentURL and therefore IFrames.
LoadOnDemand=true works perfectly for tabs created in design mode, but i have no idea, no example how i can reach the same functionality for tabs created dynamically.
Hi Pobo,
I forgot that EnableLoadOnDemand instantiates templates on demand and when templates are instantiated (or child controls are created) manually, then that property becomes irrelevant.
It means that if application creates content of tabs manually, then it should mimic logic of WebTab related to LoadOnDemand and instantiate child controls in tabs conditionally. The "condition" (list of once loaded tabs) is stored in a hidden field which has name WebTab.ClientID+'.i'. Well, that value is not public, though application may try to use it.
I wrote a sample for you, which uses that field.aspx:
<ig:WebTab ID="WebTab1" runat="server" Width="300px" Height="200px"> <AutoPostBackFlags SelectedIndexChanged="On" /></ig:WebTab><asp:Button ID="AddTabs" runat="server" Text="AddTabs" onclick="AddTabs_Click" />
asxp.cs:
protected void Page_Load(object sender, EventArgs e){ this.FillTabs();}
private void FillTabs(){ int tabsCount = this.WebTab1.Tabs.Count; if (tabsCount < 1) return; // list of loaded indexes separated by ":" string clientValue = this.Request.Form[this.WebTab1.ClientID + ".i"]; string[] indexes = string.IsNullOrEmpty(clientValue) ? new string[]{"0"} : clientValue.Split(':'); int count = indexes.Length; while (count-- > 0) { string indexStr = indexes[count]; int index = -1; if (!string.IsNullOrEmpty(indexStr) && char.IsDigit(indexStr[0])) index = int.Parse(indexStr, System.Globalization.CultureInfo.InvariantCulture); if (index < 0 || index >= tabsCount) continue; ContentTabItem tab = this.WebTab1.Tabs[index]; if (index == 0) tab.UserControlUrl = "WebUserControl1.ascx"; if (index == 1) { TextBox tb = new TextBox(); tb.ID = "TextBoxOn2ndTab"; tab.Controls.Add(tb); } if (index == 2) { TextBox tb = new TextBox(); tb.ID = "TextBoxOn3rdTab"; tab.Controls.Add(tb); } }}
protected void AddTabs_Click(object sender,EventArgs e){ if (this.WebTab1.Tabs.Count > 0) return; int i = -1; while (++i < 3) { ContentTabItem tab = new ContentTabItem(); tab.Text = "Tab" + (i + 1); this.WebTab1.Tabs.Add(tab); } this.FillTabs();}
I said that i do not have problems with EnableLoadOnDemandUrl, not with EnableLoadOnDemand.
In example, which u gave before, i dont see any dynamically added Tabs.
Here is the example with EnableLoadOnDemand and Tabs created within aspx:
<body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <ig:WebTab ID="WebTab1" runat="server" Height="300px" Width="600px" SelectedIndex="1"> <Tabs> <ig:ContentTabItem runat="server" Text="Tab 1"> <Template> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> </Template> </ig:ContentTabItem> <ig:ContentTabItem runat="server" Text="Tab 2"> <Template> <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> </Template> </ig:ContentTabItem> <ig:ContentTabItem runat="server" Text="Tab 3"> <Template> <asp:TextBox ID="TextBox3" runat="server"></asp:TextBox> </Template> </ig:ContentTabItem> <ig:ContentTabItem runat="server" Text="Tab 4"> <Template> <asp:TextBox ID="TextBox4" runat="server"></asp:TextBox> </Template> </ig:ContentTabItem> </Tabs> <PostBackOptions EnableLoadOnDemand="True" EnableLoadOnDemandViewState="True" EnableAjax="True" /> </ig:WebTab> </div> </form></body>
I need an simplest example with EnableLoadOnDemand like above, but with dynamically added Tabs and Conent please.
When you said that you do not have problems with LoadOnDemand, then I assumed that you decided to use ContentUrl instead.
As I said, there should be no difference in functionality related to LoadOnDemand if controls are created within aspx or dynamically: example, which I gave before with consistently recreated same child controls of tab items.
If application expects persisting view states and server events of child controls in tabs, then it should fill-up all tabs on any postback.
If you do not want to do that permanent "recreate" for all tabs, and want to create content of only selected tab, then that is possible as well. In my previous example, before adding child controls to tab-item, you can check if that tab-item is selected. If tab-item is not selected, then you may skip fill-in its content. Also, you do not need to enable LoadOnDemand, because that option becomes irrelevant: application already defines contents of tab by itself.
In that case, only content of selected tab-item will be created on server and go to client. That might look attractive, but that has price: no persistance of view states of tab-item children and no server events neither.In theory that side effect can be "fixed", but that requires too many coding. Basically application should reimplement all built-in architecture of server related to view state and events. For viewstates, application should create its own storage (Session can be used) and events should be raised manually. All "new" client data and event-flags should be extracted from fields while analizing content of Request.Form object.
I have no Problem with EnableLoadOnDemandUrl=True ans setting ContentURL, it works fine, but it prodused IFrames.
What i need is LoadOnDemand functionality, but WITHOUT setting ContentURL and therefore WITHOUT IFrames.
If you use ContentUrl and want to load only content of selected tab, then there is PostBackOptions.EnableLoadOnDemandUrl=true, which was designed for exactly for that scenario.
It does not matter how tabs are created statically in aspx or dynamically in cs. You do not need to wait for a postback, adjust ContentUrl for selected tab, etc. I suggest you to set ContentUrl for all tabs at the time when they are created and enable loadOnDemandUrl.
If that will not work for you, or you have different requirements, like to have full postback which will be used to defined ContentUrl for a single selected tab and remove ContentUrl for all other tabs, then I can suggest something like below:1. Set AutoPostBackFlags.SelectedIndexChanged="On"2. In cs when tabs are created, set ContentUrl only for selected tab.3. Within any postback on server, remove ContentUrl from all (already created) tabs and set ContentUrl only for selected tab.