views:

1013

answers:

1

Hi all,

I've encountered an odd problem that doesn't make any sense to me. I am trying to dynamically set up MasterPage Content controls on a page. I have it working nicely with the following code:

    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);

        MasterPageFile = "~/MasterPages/Default.master";

        string existantContentPlaceHolderID = "ContentPlaceHolder1";
        string nonExistantContentPlaceHolderID = "foo";

        //Control c = Master.FindControl(existantContentPlaceHolderID);
        //Control c1 = Master.FindControl(nonExistantContentPlaceHolderID);

        TextBox t = new TextBox
                        {
                            Text = "Text"
                        };

        ITemplate iTemplate = new GenericITemplate(container => container.Controls.Add(t));

        AddContentTemplate(existantContentPlaceHolderID, iTemplate);

    }

    public delegate void InstantiateTemplateDelegate(Control container);

    public class GenericITemplate : ITemplate
    {
        private readonly InstantiateTemplateDelegate m_instantiateTemplate;

        public void InstantiateIn(Control container)
        {
            m_instantiateTemplate(container);
        }

        public GenericITemplate(InstantiateTemplateDelegate instantiateTemplate)
        {
            m_instantiateTemplate = instantiateTemplate;
        }
    }

This works great, except I want to be able to double-check that the contentPlaceHolderIDs exist on the MasterPage before calling AddContentTemplate as the Page will throw an error if you add a Content control that points to a non-existing ContentPlaceHolder.

The problem I am having is that in the above example when I call one of the commented Master.FindControl lines, the TextBox no longer renders.

Does anyone have any ideas why this might be... I cannot makes heads or tails of what is going on.

Thanks, Max

+2  A: 

The problem is that AddContentTemplate just records its parameters in a hashtable ready to be combined with the master page instance when it is created. Calling it after the master page has been created won't do anything, and reading the Master property causes the master page to be created.

The best way I can see around this is to create a separate instance of the master page with LoadControl, which you can inspect without affecting the page's own Master property...

MasterPage testMaster = (MasterPage) LoadControl( MasterPageFile );
Control c = testMaster.FindControl(existantContentPlaceHolderID);

There's some overhead in creating a second instance, but it's not immediately obvious to me whether it will be worth worrying about.

stevemegson
hmm... thats interesting, it hadn't occured to me that accessing Master would start futzing with stuff, but that does make sense. I only have a limited number of master pages, so I'll try your solution, but throw the loaded control into a cache with a cachedependency set back to the master file...
Max Schilling