locked
Dynamically adding controls to a Templated User Control? RRS feed

  • Question

  • User314429005 posted
    A few weeks back I created a Templated User Control, for the most part based on the example here: 
    http://msdn.microsoft.com/en-us/library/36574bf6(v=VS.90).aspx

    The difference is that I did not implement the "MessageContainer" class as I wanted just an empty template that I could add whatever controls I wanted to at design time.

    This TUC has been working great, but I ran into a scenario I hadn't anticipated when I created the thing. The need to dynamically add this TUC to a page, which means that I would need to dynamically add the controls within the template of the TUC as well.

    I found another example here on how to dynamically create a Template and add it to the Templated Control:
    http://msdn.microsoft.com/en-us/library/y0h809ak(v=vs.71).aspx

    This second example article discusses only the "DataList, Repeater, and DataGrid controls" but I figure since I am using the ITemplate interface here, it should be the same thing.

    However, I am unable to get this to work, I keep getting an "Object reference not set to an instance of an object." error when I attempt to populate the TUC.

    Here's what I am doing....

    Like the example above I created an ITemplate class:

        public class XPCTemplate : ITemplate
        {
            private readonly Control _control;
            public XPCTemplate(Control control)
            {
                _control = control;
            }
    
            public void InstantiateIn(Control container)
            {
                container.Controls.Add(_control);
            }
        }


    Then, in the test page code-behind I attempt to load up and display the TUC dynamically:

            ExpandCollapseRegion xpcRegion;  // The Templated User Control
    
            protected void Page_Load(object sender, EventArgs e)
            {
                PlaceHolder ph;
                ph = {  ....  code here to dynamically create some labels, textboxes, etc.  .... };
    
                // Create an instance of the TUC
                xpcRegion = new ExpandCollapseRegion();
    
                // Pass into the TUC's template the controls dynamically created above
                xpcRegion.LayoutTemplate = new XPCTemplate(ph);
    
                // add the dynamic TUC to the page
                phDynamicUC.Controls.Add(xpcRegion);
    
                phDynamicUC.Controls.Add(new LiteralControl("<br />"));
            }


    Test page HTML Source:

    <body>
        <form id="form1" runat="server">
        <div>
        
        Dynamically Loading User Control
        <br />
        <asp:PlaceHolder ID="phDynamicUC" runat="server" />
        
        </div>
        </form>
    </body>



    When I run the page, I get the "Object reference not set to an instance of an object" error on the "container.Controls.Add(_control);" line of the XPCTemplate class. When I debug the test page and TUC control, the code of the TUC receives the XPCTemplate into its LayoutTemplate during the TUC's Page_Init() method, but when the InstantiateIn() event back in the XPCTemplate fires immediately afterwards, the "container" argument is NULL.

    I'm not sure why this is happening, it's like the InstantiateIn() method of the XPCTemplate class is trying to actually set the PlaceHolder control within the TUC rather than just passing the contents. Maybe this is supposed to be the way and I am missing something on the TUC side to allow this behavior?

    This is the first TUC I have created and likewise the first time trying to dynamically fill/load it, so I am sure I am missing something needed to accomplish this. Any help is greatly appreciated.

    -- Andrew
    Monday, August 15, 2011 3:52 PM

Answers

  • User314429005 posted
    Found the solution to the problem, which was how I was loading the TUC.

    Incorrect:
    xpcRegion = new ExpandCollapseRegion();
     
    Correct:
    xpcRegion = (ExpandCollapseRegion)LoadControl("ExpandCollapseRegion.ascx");

    Making this simple change took care of the problem. Also, found that I could forego the need for a custom ITemplate class by using the CompiledTemplateBuilder() method. Really simplifies the code.

    -- Andrew
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, August 16, 2011 11:47 AM