[CLOSED] Page.FindControl cannot find parent by id in Page_Load of UserControl that invoked by ResourceManger.RaisePostbackEvent

Page 1 of 2 12 LastLast
  1. #1

    [CLOSED] Page.FindControl cannot find parent by id in Page_Load of UserControl that invoked by ResourceManger.RaisePostbackEvent

    The reason I believe this doesn't work is that Page in this condition is a Page that is instantiated from a new SelfRenderingPage. Issue appears when I call UserControlRenderer.Render( cfg );

    To solve this problem, you need to override SelfRenderingPage.FindControls to use the original Page. You might want to override many of the default Page methods and properties (Form for example is not available either).

    At a minimum, one has every reason to believe that while within the UserControl's Page_Load, they still should have access to find controls.
    Last edited by Daniil; Jan 07, 2014 at 1:43 PM. Reason: [CLOSED]
  2. #2
    UserControl is rendered by UserControlRenderer is not related with main page at all
    I am not sure why do you expect to get references to the main page.
    UserControl is rendered in separate page and not involved to page life cycle of main page

    To solve this problem, you need to override SelfRenderingPage.FindControls to use the original Page. You might want to override many of the default Page methods and properties (Form for example is not available either).
    In this case, we need to change methods of parent page also to find user control also (find user control from parent page)

    It is not good idea because as I mentioned before, UserControlRenderer renders user control in another page context (you can render it anywhere, in http handler, web service and etc)

    If you need parent page context then you need to add user control to the page hierarchy (and do not use UserControlRenderer) or pass page reference to user control and use it as required
  3. #3
    Quote Originally Posted by Vladimir View Post
    UserControl is rendered by UserControlRenderer is not related with main page at all
    I am not sure why do you expect to get references to the main page.
    UserControl is rendered in separate page and not involved to page life cycle of main page

    In this case, we need to change methods of parent page also to find user control also (find user control from parent page)

    If you need parent page context then you need to add user control to the page hierarchy (and do not use UserControlRenderer) or pass page reference to user control and use it as required
    I have had to revert all DirectEvent/Method UserControl creation to using UserControlRender because UserControlLoader, Items.Add, Controls.Add destroy it's parent client data in DirectEvents. I would love to create UserControls reliably in the standard page-life cycle but that just has not been plausible in testing. UserControlRender has the ability to overcome this deficit and send the client new controls and attach to a parent element without breaking the parent.

    If you're curious what I'm building and you think you have a better way, I'm open. Please advise a better strategy here: http://forums.ext.net/showthread.php...-Hidden-Fields

    I'm switching to a full ajax model without frequent Page refreshes which means I need to be able to create reusable UserControls reliably that can be rendered in Page_Load or DirectEvent/Method's with heavy nesting (e.g. that have their own controls with DirectEvents/Methods). So far I have found no better way than with UserControlRender so until I've been offered a better path, all I can do is test nuances and post the issues/limits I find. Passing in the Page from the lifecycle would defeat the reusable controls requirement.

    Quote Originally Posted by Vladimir View Post
    It is not good idea because as I mentioned before, UserControlRenderer renders user control in another page context (you can render it anywhere, in http handler, web service and etc)
    I'm not suggesting you break anything with regard to how UserControlRender presently works, but extend it so it is more reusable (as you say) anywhere, i.e. not just an httphandler or webservice, etc. So by anywhere, I'm expecting it to work within the page-lifecycle as well, and I've had great success with doing so too. I'm assuming a webservice or handler wouldn't call FindControl, but in a page life-cycle, you would, so it seems reasonable to me that if you are using it in the page life-cycle case, you should have access to the full Page tree. For the meanwhile, this has seemed to do the trick...

        public partial class SelfRenderingPage {
            public override Control FindControl( string id ) {
                var ctl = base.FindControl( id );
                if( ctl != null )
                    return ctl;
                var Page = HttpContext.Current.Handler as Page;
                return ( Page != null ) ? Page.FindControl( id ) : null;
            }
        }
    Last edited by michaeld; Dec 19, 2013 at 7:00 AM.
  4. #4
    Hello!
    I saw that you created a lot of things to improve UserControls .

    I'm just curious, what kind of scenario are you trying to implement?
  5. #5
    Quote Originally Posted by Baidaly View Post
    I saw that you created a lot of things to improve UserControls .

    I'm just curious, what kind of scenario are you trying to implement?
    Please follow the link above which contains the implementation of what I'm trying to create. That thread contains a link to the original feature request.

    But in a nutshell, a reliable ajax standard with extnet to render reusable UserControls to the page without needing to refresh the page or writing alternate code to handle first page initialization versus DirectEvent/Methods. I want to be able to use the same UserControl initialization in both Page_Load or DirectEvents/Methods.


    Refreshes are expensive because of the size of the extjs/extnet js client libraries. Even on the fastest machines, client load times on complex pages are in the seconds. Mobile devices are even worse because of their lower processing power. Most of the time, it is unnecessary to reload an entire page, especially when the client already has the runtime loaded and only regions of the page need to be updated. That's where loading UserControls reliably come in. IFrames have been significantly more reliable, but as noted in other threads, they have major memory problems and also require duplication of loading the client js libraries. That's why I'm focusing on DirectEvent/Method UserControls in the same page scope in all my test.

    Once all the variations and issues with rendering extnet UserControls are remedied, I can switch to creating pages with a minimum complexity and render new controls on-demand back to the client where everything else is already loaded. It means more round-trips back to the server but far less initial load-time cost.


    Example: I load an admin page with a preview of their content available to edit. On it which is composed of UserControls, there are a few dozen menu options which launch windows with FormPanels so they can edit specifics. Each menu item click can call a DirectEvent to render only the window requested and bind the editable contents. Then the user can click save and its DirectEvent saves the content, tells the client to destroy the window and refresh only the user control that was affected or any other sections in the preview that might also be affected (that's where FindControl to the whole page becomes important). All of this is possible now with extnet, except managing the reload of the UserControls so their own DirectEvents/Methods can be called successfully. Managing reload of UserControls is at the onus of the developer. I'm trying to remedy this in that link. It's still very hard to ensure postback binds back to the proper functions because of bugs from nested UserControls variations and IDModes. I'm working through the hundred or so variations to weed out these.
    Last edited by michaeld; Dec 20, 2013 at 2:42 AM.
  6. #6
    Hi,

    UserControlRenderer assumes that you render user control without binding to concrete page context
    The fact that you call UserControlRenderer in the your page should not to be propagated to user control
    So, your user control is not related with the page and I don't see any reason to make such hack for page hierarchy.
    What if you need to find control in the user control (using FindControl), your code doesn't allow it

    If need to get reference of main page then use 'HttpContext.Current.Handler'
    imho, such overriding is not correct (in architecture term)

    I will discuss your proposal with my colleguaes and i'll let you know them opinion

    I guess it is better (if you need to persist page hierarchy) to render user control the same way
    <%@ Page Language="C#" EnableViewState="false" ClassName="Test43"  %>
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    
    
    <!DOCTYPE html>
    <script runat="server">
    
    
        protected void Render_DirectClick(object sender, DirectEventArgs e)
        {
            var ct = new Container();
            ct.ContentControls.Add(this.Page.LoadControl("Child.ascx"));
            this.Page.Controls.Add(ct);
            ct.Render("Panel1", RenderMode.AddTo);
        }
    </script>
    
    
    <html>
    <head id="Head1" runat="server">
        <title>Sample</title>
    </head>
    <body>
        <form id="Form1" runat="server">
            <ext:ResourceManager ID="ResourceManager1" runat="server" />       
            
            <ext:Button runat="server" Text="Render UserControl" OnDirectClick="Render_DirectClick" />
            <ext:Panel ID="Panel1" runat="server" Width="300" Height="300">
            </ext:Panel>
        </form>
    </body>
    </html>
  7. #7
    Quote Originally Posted by Vladimir View Post
    UserControlRenderer assumes that you render user control without binding to concrete page context
    The fact that you call UserControlRenderer in the your page should not to be propagated to user control
    So, your user control is not related with the page and I don't see any reason to make such hack for page hierarchy.
    What if you need to find control in the user control (using FindControl), your code doesn't allow it

    If need to get reference of main page then use 'HttpContext.Current.Handler'
    imho, such overriding is not correct (in architecture term)


    I guess it is better (if you need to persist page hierarchy) to render user control the same way
        protected void Render_DirectClick(object sender, DirectEventArgs e)
        {
            var ct = new Container();
            ct.ContentControls.Add(this.Page.LoadControl("Child.ascx"));
            this.Page.Controls.Add(ct);
            ct.Render("Panel1", RenderMode.AddTo);
        }
    </script>
    I agree with everything you're saying. UserControlRender was not my first choice. It became my last resort after trying a dozen or so strategies working with Daniil. This is the first alternate model from ones suggested to try, so thank you. I will try and report back.

    Quote Originally Posted by Vladimir View Post
    I will discuss your proposal with my colleguaes and i'll let you know them opinion
    I'm going to assume you mean the whole model I presented as a feature request here:
    http://forums.ext.net/showthread.php...er-amp-Manager

    I won't presume this is the only best way, but to me, it's a logical next step to a comprehensive ajax solution.

    Check my implementation, to get the ordering right, I had to move final loading of the registered controls till after all controls Page_Load. I did this by overriding Page.RaisePostBackEvent. But it would be more natural in ResourceManager.RaisePostBackEvent.
    Implementation here: http://forums.ext.net/showthread.php...873#post122873

    So far it just works. The reason is because each add of a registered control adds a hidden field and they return to the post in the same order they were created. It may be safer to just use numbering instead. Though I trust your skill to put the whole thing together even better than I have.
  8. #8
    I'm assuming this mode does not participate in layout; therefore it's like ContentControls. If the UserControl has asp WebControls, it needs to be based on Form. Also, I don't like the fact that it has the wrong parent, so instead, can't I change it to Add to the Controls of the Parent? And I think it's advisable to set the ID. Also wouldn't it be better to make ct a new Component() instead?
        protected void Render_DirectClick(object sender, DirectEventArgs e)
        {
            var ct = new Container();
            var uc = Page.LoadControl("Child.ascx");
            uc.ID = "uc1";
            ct.ContentControls.Add();
            Panel1.Controls.Add(ct);
            ct.Render("Panel1", RenderMode.AddTo);
        }
    How can I do the same AddTo with Items to participate in layout? I tried with UserControlLoader and it doesn't work.
    Last edited by michaeld; Dec 21, 2013 at 12:08 PM.
  9. #9

    See implementation...

    I've taken your suggestions and extended them to the latest implementation found here:
    http://forums.ext.net/showthread.php...026#post123026
  10. #10
    Quote Originally Posted by michaeld View Post
    I'm assuming this mode does not participate in layout; therefore it's like ContentControls. If the UserControl has asp WebControls, it needs to be based on Form. Also, I don't like the fact that it has the wrong parent, so instead, can't I change it to Add to the Controls of the Parent? And I think it's advisable to set the ID. Also wouldn't it be better to make ct a new Component() instead?
        protected void Render_DirectClick(object sender, DirectEventArgs e)
        {
            var ct = new Container();
            var uc = Page.LoadControl("Child.ascx");
            uc.ID = "uc1";
            ct.ContentControls.Add();
            Panel1.Controls.Add(ct);
            ct.Render("Panel1", RenderMode.AddTo);
        }
    How can I do the same AddTo with Items to participate in layout? I tried with UserControlLoader and it doesn't work.
    In this code the "ct" should participate in the Panel1's layout.
        protected void Render_DirectClick(object sender, DirectEventArgs e)
        {
            var ct = new Container();
            var uc = Page.LoadControl("Child.ascx");
            uc.ID = "uc1";
            ct.ContentControls.Add(uc);
            Panel1.Items.Add(ct);
            ct.Render();
        }
Page 1 of 2 12 LastLast

Similar Threads

  1. WakeUp parent page on usercontrol event
    By immanegiuv in forum 1.x Help
    Replies: 1
    Last Post: Dec 02, 2011, 10:36 AM
  2. Replies: 16
    Last Post: Jul 19, 2011, 3:53 AM
  3. Replies: 3
    Last Post: Aug 02, 2010, 11:06 AM
  4. Replies: 16
    Last Post: Jun 24, 2010, 2:41 PM
  5. Replies: 6
    Last Post: Mar 12, 2010, 12:34 AM

Posting Permissions