[OPEN] [#403] UserControlRendererConfig does not render some controls

Page 1 of 2 12 LastLast
  1. #1

    [OPEN] [#403] UserControlRendererConfig does not render some controls

    ..........
    Last edited by Daniil; Dec 16, 2013 at 3:35 PM. Reason: [OPEN] [#403]
  2. #2
    Is there a way to get the reference to the UserControl rendered from UserControlRendererConfig? I attempted to get it from the ComponentAddedEventArgs.Control but it isn't the same. I use the actual UserControl's ClientID to bind objects.
    Last edited by michaeld; Dec 02, 2013 at 2:16 AM.
  3. #3

    I think I got it...

    		public static void AddDirectControl( this ComponentBase ctnr, string ctlPath, string ctlName, BindFn bindFn = null ) {
    			UserControlRendererConfig cfg = new UserControlRendererConfig {
    				UserControlPath = ctlPath,
    				UserControlId = ctlName,
    				UserControlClientIDMode = System.Web.UI.ClientIDMode.Static,
    				Mode = RenderMode.AddTo,
    				Element = ctnr.ClientID
    			};
    			if( bindFn!=null ) {
    				cfg.BeforeRender += delegate( ComponentAddedEventArgs eCmp ) {
    					bindFn( ((Container)eCmp.Control).ContentControls[0] );
    				};
    			}
    			X.DirectRendering = true;
    			UserControlRenderer.Render( cfg );
    			X.DirectRendering = false;
    		}
  4. #4
    Hi @michaeld,

    It will work only if:
    if (config.ControlIdToRender.IsEmpty() && !config.SingleControl)
    where "config" - a UserControlRendererConfig instance.

    It is an excerpt from the UserControlRenderer's Build method (in UserControlScriptBuilder.cs).

    Please note that in your case even if
    Mode = RenderMode.AddTo
    an intermediary Container is created and the user control's content is rendered to that Container as Content (not as Items). Then that Container is rendered to the Element using RenderMode.AddTo.

    UserControlRenderer doesn't extract Ext.NET components from a user control, as UserControlLoader does.

    Maybe, it is better to use a UserControlLoader instead of UserControlRenderer? There is the UserControlAdded event in UserControlLoader.

    Also, we are considering a possibility to pass a user control into a UserControlRenderer's BeforeRender handler.
    Last edited by Daniil; Dec 02, 2013 at 10:54 AM.
  5. #5
    Quote Originally Posted by Daniil View Post
    It will work only if:
    if (config.ControlIdToRender.IsEmpty() && !config.SingleControl)
    where "config" - a UserControlRendererConfig instance.
    I found that if you set SingleControl on a UserControl, it ONLY renders the first item. This was actually the issue I was having that originated this thread. I figured that out and couldn't understand under any condition that might be appropriate to just render the first item in a UserControl (unless you know for sure it's just a single item). Honestly, I don't know where this class is documented well enough to understand all all the variations and how it can be properly used. I've come up with an extension above that ensures, at least so far, the user control is the only part that's rerendered without its parent as well. It handles autoloaders as well.

    Quote Originally Posted by Daniil View Post
    It is an excerpt from the UserControlRenderer's Build method (in UserControlScriptBuilder.cs).

    Please note that in your case even if
    Mode = RenderMode.AddTo
    an intermediary Container is created and the user control's content is rendered to that Container as Content (not as Items). Then that Container is rendered to the Element using RenderMode.AddTo.

    UserControlRenderer doesn't extract Ext.NET components from a user control, as UserControlLoader does.

    Maybe, it is better to use a UserControlLoader instead of UserControlRenderer? There is the UserControlAdded event in UserControlLoader.
    I'm not sure I'm following exactly how your posing a better solution. Please post a rewrite of a better implementation of the extension method that handles items. I just need one reliable way for content and one for items that only renders the user control and adds it to a parent.
  6. #6
    Re: SingleControl

    By default, UserControlRenderer creates an intermediary Container and put a user control to its ContentControls.

    Let's consider an example.

    Page
    <%@ Page Language="C#" %>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    
    <script runat="server">
        protected void RenderUserControl(object sender, DirectEventArgs e)
        {
            UserControlRenderer.Render(new UserControlRendererConfig() 
            { 
                Element = this.Panel1.ClientID,
                UserControlPath = "TestUC.ascx",
                Mode = RenderMode.AddTo
            });
        }
    </script>
    
    <!DOCTYPE html>
    <html>
    <head runat="server">
        <title>Ext.NET v2 Example</title>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager runat="server" />
    
            <ext:Button runat="server" Text="Render User Control" OnDirectClick="RenderUserControl" />
    
            <ext:Panel
                ID="Panel1"
                runat="server" 
                Title="Panel" 
                Height="200"
                Layout="FitLayout" />
        </form>
    </body>
    </html>
    User Control
    <%@ Control Language="C#" %>
    
    <ext:Container runat="server" Html="User Control" StyleSpec="background-color: yellow;" />
    If you run it, you will see that the Panel1's FitLayout doesn't affect the Container inside the user control. It is because there is an intermediary Container between them. So, the Panel1's FitLayout affects that intermediary Container which has no layout itself.

    A developer can set up SingleControl="true" (or ControlIdToRender) to avoid that intermediary Container. In other words, a developer can define an intermediary Container himself if there are several controls to render, not just the only one.

    But an intermediary Container is required in a general case, because a user control can look like this one:

    User Control
    <%@ Control Language="C#" %>
    
    <script>
        alert("Hello!");
    </script>
    
    <asp:Panel runat="server">
        ASP.NET Panel
    </asp:Panel>
    
    <ext:Container runat="server" Html="User Control" StyleSpec="background-color: yellow;" />
    Generally speaking, the SingleControl option is quite out-of-date, becase now there is this setting.
    Items = true
    With this setting the UserControlRender will extract all the Ext.NET controls (top level) from the user control and render it without an intermediary Container.

    Though, we keep SingleControl to avoid making a breaking change just removing that.

    Re: UserControlRenderer vs UserControlLoader

    I said that the UserControlRenderer cannot retrieve Ext.NET controls from a user control, but I just forgot about the "Items = true" option. So, it is not the benefit of UserControlLoader and you can use UserControlRenderer reliably.

    Re: getting the user control in the BeforeRender handler

    void cfg_BeforeRender(ComponentAddedEventArgs args)
    {
        UserControl uc = ((args.Control as Container).ContentControls[0]) as UserControl;
    }
    Honestly, I don't know where this class is documented well enough to understand all all the variations and how it can be properly used.
    The lack of good docs is one of our main problems. We apologize for the inconveniece. Hopefully, my explanation helps a bit.
    Last edited by Daniil; Dec 10, 2013 at 12:37 PM.
  7. #7
    If I could use UserControlLoader with a render and find a way to add it to a parent, that would be ideal? If this is possible, please let me know with an example. Or are you saying the better way is to set items=true on a UserControlRenderer to render just the control and it will attach to items to become part of the parent layout? Again, the goal is to only render the new control and attach it to the parent in a DirectEvent without rerendering the parent too (which clobbers the parent's other control values).

    As for the lack of documentation, hopefully this detail you supply will help others too now or in the future. What vladimir did in the other thread was pretty awesome showing variations and examples.
  8. #8
    So I'm finding this model doesn't work either if the user control being loaded has its own DirectEvents.
  9. #9
    So I'm finding this model doesn't work either if the user control being loaded has its own DirectEvents.
    It is true for any dynamic ASP.NET control which has event handler and which is not recreated on next requests (for example, ASP.NET button with Click event handler)
    Vladimir Shcheglov
    Sr. Developer
  10. #10
    Quote Originally Posted by Vladimir View Post
    It is true for any dynamic ASP.NET control which has event handler and which is not recreated on next requests (for example, ASP.NET button with Click event handler)
    I do reload it on postback.
    aspx
    <%@ Page Language="C#" EnableViewState="false" %>
    
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e) {
            if( X.IsAjaxRequest && ucLoaded.Text == "1" ) {
                var uc = Page.LoadControl( "Test39.ascx" );
                uc.ID = "uc1";
                uc.ClientIDMode = System.Web.UI.ClientIDMode.Predictable;
                Form.Controls.Add(uc);
            }        
        }
        protected void CreateTest( object sender, DirectEventArgs e ) {
            UserControlRendererConfig cfg = new UserControlRendererConfig {
                UserControlPath = "Test39.ascx",
                UserControlId = "uc1",
                UserControlClientIDMode = System.Web.UI.ClientIDMode.Predictable,
                Mode = RenderMode.AddTo,
                Element = RP.ClientID
            };
            UserControlRenderer.Render( cfg );
            ucLoaded.Text = "1";
        }
    </script>
    
    
    <!DOCTYPE html>
    <html>
    <head id="Head1" runat="server">
        <title>Ext.NET Example</title>
    </head>
    <body>
        <form id="Form1" runat="server">
    
    
            <ext:ResourceManager ID="ResourceManager1" runat="server" ScriptMode="Development" SourceFormatting="true" />
            <ext:Viewport ID="vp" runat="server" Layout="HBoxLayout">
                <Items>
    
    
                    <ext:Container ID="LP" runat="server" Border="true" Padding="5" Flex="1" Layout="FitLayout">
                        <Items>
                            <ext:Button runat="server" Text="Test Right Panel Load">
                            <DirectEvents>
                                <Click OnEvent="CreateTest" />
                            </DirectEvents>
                            </ext:Button>                                
                            <ext:Hidden ID="ucLoaded" runat="server" Text="0" />
                        </Items>
                    </ext:Container>
    
    
                    <ext:Container ID="RP" runat="server" Flex="1" Layout="VBoxLayout">
                        <Items>
                        </Items>
                    </ext:Container>
    
    
                </Items>
            </ext:Viewport>
        </form>
    </body>
    </html>
    aspx
    <%@ Control Language="C#" ClassName="Test39" %>
    
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e) {
        }
        protected void MsgTest( object sender, DirectEventArgs e ) {
            HeadL.InnerHtml = "This text was changed";
            Button1.Text = "Proves button changed in directEvent";
            ASPButton.Text = "Changed aspbutton";
            Button1.Listeners.Render.Handler = "alert('Test');";
            Button1.Render();
        }
    </script>
    
    
    <ext:Panel ID="EventP" runat="server" Flex="1" Padding="5" Title="TestRightPanel">
        <Content>
    
    
            <div class="TitlePnl">
                <h1 id="TitleL" runat="server" class="Title">Test Title</h1>
                <div class="HeadPnl">
                    <span id="HeadL" runat="server" class="Head">Test Span</span>
                </div>
                <asp:Button ID="ASPButton" runat="server" Text="AspButton" />
            </div>
    
    
        </Content>
        <Items>
            <ext:Button ID="Button1" runat="server" Text="Test DirectEvent in Loaded Control" IDMode="Static">
                <DirectEvents>
                    <Click OnEvent="MsgTest" />
                </DirectEvents>
                <Listeners>
                    <AfterRender Handler="" />
                </Listeners>
            </ext:Button>
        </Items>
    </ext:Panel>
    This renders the following:
    {script:"Ext.net.append(Ext.getBody(),[\"<div id=\\\"uc1_ct_Content\\\" class=\\\"x-hidden\\\"><div id=\\\"App.EventP_Container\\\"><div id=\\\"uc1_EventP_Content\\\" class=\\\"x-hidden\\\">\",\"<div class=\\\"TitlePnl\\\">\",\"<h1 id=\\\"uc1_TitleL\\\" class=\\\"Title\\\">Test Title</h1>\",\"<div class=\\\"HeadPnl\\\">\",\"<span id=\\\"uc1_HeadL\\\" class=\\\"Head\\\">Test Span</span>\",\"</div>\",\"<input type=\\\"submit\\\" name=\\\"uc1$ASPButton\\\" value=\\\"AspButton\\\" id=\\\"uc1_ASPButton\\\" />\",\"</div>\",\"</div></div>\",\"</div>\"].join(''));Ext.net.ResourceMgr.destroyCmp(\"App.uc1_ct\");Ext.create(\"Ext.panel.Panel\",{id:\"EventP\",padding:5,renderTo:\"App.EventP_Container\",flex:1,contentEl:\"uc1_EventP_Content\",items:[{id:\"Button1\",xtype:\"button\",text:\"Test DirectEvent in Loaded Control\",directEvents:{click:{fn:function(item,e){Ext.net.directRequest({control:this});}}}}],title:\"TestRightPanel\"});App.RP.add({id:\"uc1_ct\",xtype:\"container\",contentEl:\"uc1_ct_Content\"});App.ucLoaded.setValue(\"1\");"}
    The issue is that despite all IDModes set to Predictable, EventP.IDMode=Static is not rendered with the Predictable naming format. I can get this whole thing working if I set modes to Static and set EventP to Static but I shouldn't have to do that. I think there is a bug.
Page 1 of 2 12 LastLast

Similar Threads

  1. Replies: 5
    Last Post: Nov 03, 2011, 2:39 AM
  2. ComboBox/Controls Render Improperly
    By Tbaseflug in forum 1.x Help
    Replies: 6
    Last Post: Mar 15, 2011, 1:44 PM
  3. Page Render - Controls all strange
    By Tbaseflug in forum Bugs
    Replies: 0
    Last Post: Jun 26, 2009, 1:27 PM
  4. Replies: 9
    Last Post: May 11, 2009, 4:06 PM
  5. Can't render window controls
    By Snargleflap in forum 1.x Help
    Replies: 3
    Last Post: May 07, 2009, 4:27 PM

Tags for this Thread

Posting Permissions