469,933 Members | 2,386 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,933 developers. It's quick & easy.

Programmatically adding ASP.net User Control to UpdatePanel

Hi All, I got a real doozy here. I have read hundreds upon hundreds of forum posts and found numerous others who have replicated this problem, but have yet to find a solution. Through testing I have been able to find the cause of the problem, and will describe it here first textually and then through a code example.

The purpose of what I am trying to do is to create a postback-free web application through the use of ASP.net AJAX UpdatePanels and User Controls. When programmatically adding a User Control to a web page through a normal postback everything works fine. All the controls within the user control are registered properly in the page and any update panels included in the user control also work properly. HOWEVER, if instead of using a full postback you use an UpdatePanel and a partial page update of the UpdatePanel the controls do not get registered with the page and events from them do not fire (for instance, a button click event never hits the event breakpoint).

Because the very same user control works fine if loaded in a full postback or dynamically added from a namespace works fine, I can be relatively sure that it only is trouble when loading via a partial page update into an UpdatePanel. I load the control via the LoadConrol method and then add it to the page via a PlaceHolder control. Theoretically, adding the User Control to the PlaceHolder should register itself and it's controls and events with the page, but it does not.

The following code sample is a UpdatePanel-free page using a user control that works, later I will show the same code with an UpdatePanel that does not.

I think I need to figure out how to register the controls and their events with the page without going through a full page postback. Any suggestions??

This example works as expected:
Default.aspx:
Expand|Select|Wrap|Line Numbers
  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head runat="server">
  6.     <title>Untitled Page</title>
  7. </head>
  8. <body>
  9.     <form id="form1" runat="server">
  10.         <div>
  11.             <asp:PlaceHolder ID="UCPlaceHolder" runat="server"></asp:PlaceHolder>
  12.         </div>
  13.     </form>    
  14. </body>
  15. </html>
Default.aspx.cs:
Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Web;
  5. using System.Web.Security;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8. using System.Web.UI.WebControls.WebParts;
  9. using System.Web.UI.HtmlControls;
  10.  
  11. public partial class _Default : System.Web.UI.Page 
  12. {
  13.     protected void Page_Load(object sender, EventArgs e)
  14.     {
  15.         Control ctl = LoadControl("~/UserControlDemo.ascx");
  16.         ctl.ID = "UC1";
  17.         this.UCPlaceHolder.Controls.Add(ctl);
  18.     }
  19. }
UserControlDemo.ascx:
Expand|Select|Wrap|Line Numbers
  1. <%@ Control Language="C#" AutoEventWireup="true" CodeFile="UserControlDemo.ascx.cs" Inherits="UserControlDemo" %>
  2. <asp:Button ID="Button1" runat="server" Text="Display from UC" OnClick="Button1_Click" />&nbsp;<br />
  3. <br />
  4. <asp:Label ID="Content" runat="server" Text="Content"></asp:Label>
UserControlDemo.ascx.cs:
Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Collections;
  5. using System.Web;
  6. using System.Web.Security;
  7. using System.Web.UI;
  8. using System.Web.UI.WebControls;
  9. using System.Web.UI.WebControls.WebParts;
  10. using System.Web.UI.HtmlControls;
  11.  
  12. public partial class UserControlDemo : System.Web.UI.UserControl
  13. {
  14.     protected void Page_Load(object sender, EventArgs e)
  15.     {
  16.     }
  17.     protected void Button1_Click(object sender, EventArgs e)
  18.     {
  19.         Content.Text = "Content Changed.";
  20.     }
  21. }
Now, consider this variation, where instead of loading the control in the PageLoad event, you do so programmatically via a button Click event. This does not work as it cause a full postback which refreshes the placeholder. Viewstate does not seem to be working in this case. (uses the same user control as the previous example)

Default.aspx:
Expand|Select|Wrap|Line Numbers
  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head runat="server">
  6.     <title>Untitled Page</title>
  7. </head>
  8. <body>
  9.     <form id="form1" runat="server">
  10.         <div>
  11.             <asp:Button ID="Button1" runat="server" Text="Load User Control" OnClick="Button1_Click" />&nbsp;
  12.             <br />
  13.             <br />
  14.             <asp:PlaceHolder ID="UCPlaceHolder" runat="server"></asp:PlaceHolder>
  15.         </div>
  16.     </form>    
  17. </body>
  18. </html>
Default.aspx.cs:
Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Web;
  5. using System.Web.Security;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8. using System.Web.UI.WebControls.WebParts;
  9. using System.Web.UI.HtmlControls;
  10.  
  11. public partial class _Default : System.Web.UI.Page 
  12. {
  13.     protected void Page_Load(object sender, EventArgs e)
  14.     {
  15.     }
  16.     protected void Button1_Click(object sender, EventArgs e)
  17.     {
  18.         Control ctl = LoadControl("~/UserControlDemo.ascx");
  19.         ctl.ID = "UC1";
  20.         this.UCPlaceHolder.Controls.Add(ctl);
  21.     }
  22. }
To solve this postback problem, one would naturally want to use an UpdatePanel, like the following example. However this does not work as the controls do not seem to get registered with the page, and further nesting of user controls in UpdatePanels (to create a postback free app) are no better.

Default2.aspx:
Expand|Select|Wrap|Line Numbers
  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4.  
  5. <html xmlns="http://www.w3.org/1999/xhtml" >
  6. <head runat="server">
  7.     <title>Untitled Page</title>
  8. </head>
  9. <body>
  10.     <form id="form1" runat="server">
  11.     <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"></asp:ScriptManager>
  12.     <div>
  13.         <asp:UpdatePanel ID="UpdatePanel2" runat="server">
  14.             <ContentTemplate>
  15.                 <asp:Button ID="Button1" runat="server" Text="Load User Control into UpdatePanel" OnClick="Button1_Click" />
  16.             </ContentTemplate>
  17.         </asp:UpdatePanel>
  18.         <br />
  19.         <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
  20.             <ContentTemplate>
  21.                 <asp:PlaceHolder ID="ContentPlaceHolder" runat="server"></asp:PlaceHolder>
  22.             </ContentTemplate>
  23.             <Triggers>
  24.                 <asp:AsyncPostBackTrigger ControlID="Button1" />
  25.             </Triggers>
  26.         </asp:UpdatePanel>
  27.     </div>
  28.     </form>
  29. </body>
  30. </html>
Default2.aspx.cs:
Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Collections;
  5. using System.Web;
  6. using System.Web.Security;
  7. using System.Web.UI;
  8. using System.Web.UI.WebControls;
  9. using System.Web.UI.WebControls.WebParts;
  10. using System.Web.UI.HtmlControls;
  11.  
  12. public partial class Default2 : System.Web.UI.Page
  13. {
  14.     protected void Page_Load(object sender, EventArgs e)
  15.     {
  16.  
  17.     }
  18.     protected void Button1_Click(object sender, EventArgs e)
  19.     {
  20.         Control ctl = LoadControl("~/UserControlDemo.ascx");  //loads into the page
  21.         ctl.ID = "UC1";
  22.         this.ContentPlaceHolder.Controls.Add(ctl); //adds to page control tree (or at least it should)
  23.     }
  24. }
I know I can use the "visible" property of my controls to toggle them on and off a page to create a flicker free experience, however, my application is a database intensive app and I don't want the page running queries against the database unless I'm absolutely sure the user wants them. Rendering a 10 forms and keeping them hidden isn't a big deal, but running 10 queries that the user never wants to see is, otherwise I'd stick to that method, its works perfectly. Any suggestions? Or requests for clarification? Any help you can provide is much appreciated...
Jun 16 '07 #1
15 32979
senaka
23
try this.... UpdatePanel.Controls.Add(control_name) instead of this.ContentTemplate.Controls.Add(control_name). Because, this refers to the page as a whole and not to your update panel.

the Visibility issue works well if your control is embedded inside a Panel... Therefore, if the panel is not visible, your controls wont get loaded.

Regards,
Senaka
Jun 16 '07 #2
try this.... UpdatePanel.Controls.Add(control_name) instead of this.ContentTemplate.Controls.Add(control_name). Because, this refers to the page as a whole and not to your update panel.

the Visibility issue works well if your control is embedded inside a Panel... Therefore, if the panel is not visible, your controls wont get loaded.

Regards,
Senaka
Hey Senaka,
thanks for your suggestion. No matter which combination of Controls.Add() I use it doesn't seem to make a difference as long as the User Control is added to a UpdatePanel. The control itself will load, but none of the controls or properties or events therein are accessible.

Ideally, I'd like to be able to keep using UpdatePanels, PlaceHolders, and User Controls to create a postback-free UI. Right now I'd have to settle for a postback on every page with only parts of the UI AJAXified.
Jun 16 '07 #3
Frinavale
9,735 Expert Mod 8TB
Hey Senaka,
thanks for your suggestion. No matter which combination of Controls.Add() I use it doesn't seem to make a difference as long as the User Control is added to a UpdatePanel. The control itself will load, but none of the controls or properties or events therein are accessible.

Ideally, I'd like to be able to keep using UpdatePanels, PlaceHolders, and User Controls to create a postback-free UI. Right now I'd have to settle for a postback on every page with only parts of the UI AJAXified.
I don't know if this can help you but have you thought about putting the UpdatePanel into your user control instead of adding your user control to the update panel?

-Frinny
Jun 17 '07 #4
I don't know if this can help you but have you thought about putting the UpdatePanel into your user control instead of adding your user control to the update panel?

-Frinny
Hey Frinny,
Thanks for the reply. Good suggestion, I have tried that, but it makes no difference whether the UpdatePanel is in the user control because even if it was the page wouldn't know it. It visually loads the user control, but does not programmatically register it's controls or events.

-chris
Jun 17 '07 #5
Frinavale
9,735 Expert Mod 8TB
Hey Frinny,
Thanks for the reply. Good suggestion, I have tried that, but it makes no difference whether the UpdatePanel is in the user control because even if it was the page wouldn't know it. It visually loads the user control, but does not programmatically register it's controls or events.

-chris
This is an interesting problem.
It seems to me that because you register a control with the page, and because the page is only rendered once, you might have an impossible task at hand....unless you do a postback to register the control with the page, but you don't want to do that. I believe you're going to have to re-think your system....

I'm interested to know how you solve this problem.

-Frinny
Jun 18 '07 #6
This is an interesting problem.
It seems to me that because you register a control with the page, and because the page is only rendered once, you might have an impossible task at hand....unless you do a postback to register the control with the page, but you don't want to do that. I believe you're going to have to re-think your system....

I'm interested to know how you solve this problem.

-Frinny
You hit the nail on the head. I can't believe that ASP.net AJAX has such a gaping hole in it, otherwise it's really an incomplete framework. Most other AJAX frameworks can do this, but I'd like to stay with the development ease of ASP.net AJAX. If I find a solution I'll pass it along!
Jun 18 '07 #7
amodi
1
Hi ChrisCicc,
I ran into the same problem, did you find the solution?
Thanks.
Nov 15 '09 #8
JWelch
3
I am so happy to finally find I am not the one with this problem. Did you find an appropriate solution yet? I have an update panel that loads a user control. The user control has an updatepanel containing a datalist. Outside of this updatepanel is an Add link. The Add link works great, but the "Remove" link tied to the datalist does not.

So - any solutions would be great to hear.

Many thanks!
Dec 8 '09 #9
Frinavale
9,735 Expert Mod 8TB
I just looked over the code posted in the original post and I realized that the original-poster is using the LoadControl method in the PageLoad event.

This could be causing all of the problems. Try moving this to the Page Init event instead.

http://bytes.com/topic/net/insights/...ntrols-asp-net

The ViewState contains state information about the control. If your dynamic control was a TextBox, the text that the user entered into the TextBox is loaded into the Server Side TextBox object when the ViewState is loaded for this dynamic TextBox happens.

Likewise, if you have a dynamic button and the user clicks the button, the button click event is detected when the ViewState is loaded for the button control.

If you do not instantiate your dynamic controls in the Page Init event then any events or other ViewState data will not properly be loaded and your code wont work as you expect it.

The crazy thing is that instantiating your dynamic controls elsewhere in the page life cycle will also work...but just not always.

Try this and let me know if it gets you anywhere.

-Frinny
Dec 8 '09 #10
JWelch
3
Yes, I had also seen this issue. I am using base classes for my user controls and my user controls are loading other usercontrols. Basically, we only want to load things onto the page when the user clicks for them.

I did find something interesting. If you register the user control on the page and then load it in via the placeholder, the events are fired just fine.

So the problem really is in relation to the controls being initialized fully prior to loading and using them.

Since we have a variety of controls we can be loading in depending on what was clicked, my end result will likely involve me setting the class property along with the control path for loading.

Two other important things are:
1) Make sure to always set an ID
2) Use Page.LoadControl when loading from base classes

I'll let you know what the final solution ends up being after it is well tested.
Dec 9 '09 #11
Frinavale
9,735 Expert Mod 8TB
I'll let you know what the final solution ends up being after it is well tested.
I'm looking forward to what you end up doing.

-Frinny
Dec 9 '09 #12
JWelch
3
I also forgot that you can register your usercontrols in the web.config in the <controls> section. While you wouldn't want to do this for a large number of controls, it does allow all pages to access these controls when needed. So, if you have a few controls that you need to load dynamically at different points, this is a good solution. I am only doing this for the 4 that I need access to for the async postbacks.

Using the web.config for is also good for things like headers and footers that every page uses. Just keep in mind that this slows down the initial start of the site vs. taking this time on the pages that use the controls so you should consider these tradeoffs.

I hope this is of help to others,

Jayme
Dec 10 '09 #13
Two other important things are:
1) Make sure to always set an ID
2) Use Page.LoadControl when loading from base classes
JWelch you saved my day !! I've been on this issue for 3 days now and this solved everything. I LOVE you man !
Feb 26 '10 #14
Ghayas
6
Hi JWelch ,
i have a vb file lets say abc.vb placed under app_code
i have defined <add tagPrefix="Custom" namespace="abc" />
in webconfig file under controls tag,
when i use it in my page its show an error that webconfig file is missing
what m i doing wrong,
thanks
Apr 28 '10 #15
JWelch ,quentez

I am on exactly same isuue.
I have a tab container with 4 tab panels.

In each tab panel i hv an update panel with a trigger to click a button and a placeholder for user control.

on tab click i am firing the trigger eevnt .. the control is getting loaded in the place holder..
But when i click on the next tab my usercontrol in the First tab disappear.

I hv also made sure that once the tab is loaedd then it won't fire a postback trigger.

Please help..

I want once the user control is loaded in the tab it will remain thier as it is .. no more posstbacks..

PLEASE HELP.. I am stuck here for days... :(
Sep 24 '10 #16

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

1 post views Thread by ravi sankar | last post: by
1 post views Thread by Marc Bishop | last post: by
1 post views Thread by francois | last post: by
3 posts views Thread by John Hughes | last post: by
reply views Thread by yohaas | last post: by
2 posts views Thread by C | last post: by
4 posts views Thread by archana | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.