views:

1856

answers:

3

Trying to set the value of a literal user control on my child master page via the code behind of the same master page.

Here is example of the code I am using:

Global.master

<form id="form1" runat="server">
<div>
    <asp:ContentPlaceHolder id="GlobalContentPlaceHolderBody" runat="server">

    </asp:ContentPlaceHolder>
</div>
</form>

Template.master (child of Global.master)

<asp:Content ID="TemplateContentBody" ContentPlaceHolderID="GlobalContentPlaceHolderBody" Runat="Server">
<asp:Literal ID="MyLiteral1" runat="Server"></asp:Literal>

<p>This is template sample content!</p>
  <asp:ContentPlaceHolder ID="TemplateContentPlaceHolderBody" runat="server">

</asp:ContentPlaceHolder>

Template.master.cs

    protected void Page_Load(object sender, EventArgs e)
{
    MyLiteral1.Text = "Test";
}

ContentPage.aspx

< asp:Content ID="ContentBody" ContentPlaceHolderID="TemplateContentPlaceHolderBody" Runat="Server">
</asp:Content>

Once I am able to achieve this, I will also need to be able to access content on the global and template master pages via content pages.

A: 

EDIT: This is my answer when I thought you were trying to access a control on the child master from the parent master code behind.

You can use a recursive findControl function:

protected Control FindControlRecursive(string id, Control parent)
{
    // If parent is the control we're looking for, return it
    if (string.Compare(parent.ID, id, true) == 0)
        return parent;

    // Search through children
    foreach (Control child in parent.Controls)
    {
        Control match = FindControlRecursive(id, child);

        if (match != null)
            return match;
    }

    // If we reach here then no control with id was found
    return null;
}

Then use this code in your master page:

protected void Page_Load(object sender, EventArgs e)
{
//EDIT: if GlobalContentPlaceHolderBody isn't visible here, use this instead:
//Control c = FindControlRecursive("MyLiteral1", Page.FindControl("GlobalContentPlaceHolderBody"));
    Control c = FindControlRecursive("MyLiteral1", GlobalContentPlaceHolderBody);
    if(c != null)
        ((Literal)c).Text = "Test";
}
Chris
Where do I put the protected Control FindControlRecursive? If I add it to the Template.master.cs, I get the error: The name 'GlobalContentPlaceHolderBody' does not exist in the current context.
Developr
For accessing a user control in the master via a content page, it was simple. Added the following to the template.master.cs: public string ContentLabelDemoPublic { set { ContentLabelDemo.Text = value; } }and then in the content page I could add:((MasterPages_Template)Master).ContentLabelDemoPublic = "Label on child master page exposed using public variable updated by content page";Accessing the nested master page via its own code-behind should not be that difficult.
Developr
GlobalContentPlaceHolderBody was the id of your Container. If that is not visible to your code, you can use Page.FindControl("GlobalContentPlaceHolderBody");
Chris
You'll want to add the FindControlRecursive to the master page.
Chris
The reason why this is more complex than a child accessing a control on the master is because a master page is always there. But a child control isn't guaranteed to always be there.
Chris
Sorry, just to clarify.. when you say "add the FindControlRecursive to the master page", you mean the parent master or child master? Also, if it is the child's codebehind, then it should always be there.
Developr
I'm sorry, I misread your question. I thought you were trying to access a control on the child master from the code behind of the global master. I will update my answer to be more appropriate.
Chris
No worries... I found another solution and posted, but I will try your solution as well and report back. Thanks for the effort so far!
Developr
Still getting error: The name 'GlobalContentPlaceHolderBody' does not exist in the current context
Developr
Chris, I was able to use the recursive find control to access a control in the nested child from the global master as that seems to be the only way.
Developr
Yeah, and that is what the code was intended for. I'm glad I was able to help, even though it wasn't for the question asked ;)
Chris
+1  A: 

Found a working solution. In the template.master (nested child master), I had to put the code in OnLoad event.

protected override void OnLoad(EventArgs e)
{
    MyLiteral1.Text= "<p>MyLiteral1 Successfully updated from nested template!</p>";
    base.OnLoad(e);
}

Very strange...

Basically, I am using the global master as the page that has code shared on every page, then I will have various nested pages to suit each website section. For the navigation nested template, I want to be able to show if the user is logged in and how many items in shopping cart.

If there is a better way to achieve this, I am open to suggestions.

Developr
This is the way to do it. It is strange that this didn't work in the Page_Load.
Chris
+2  A: 

If I understand your scenario you want to have your content pages access items from your master pages. If so, you'll need to setup a property to expose them from your master page, and in your content page you can setup a MasterType directive.

Take a look at this post for an example.

Ahmad Mageed
Your title sort of conflicts with your last sentence, "... I will also need to be able to access content ... via content pages." The answer I'm proposing covers this situation, unless you're trying to do something from the master pages instead.
Ahmad Mageed
+1 If all we're talking about is accessing a control on a parent master page, the MasterType directive is what we're looking for.
Alexis Abril
Ahmad, I was trying to access a control on a nested child master page via it's own code behind. The fix was to call it in the OnLoad event.Alexis - MasterType directive is useful for accessing via a content page, not from within a nested master page itself.
Developr