Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Inside my ASP.NET application all my web content pages are derived from a base class which is derived from System.Web.UI.Page. Inside this base class I need to get some controls found in one derived class, SamplePage.aspx : BaseClass.cs. It I add the C# code below on Page Load inside SamplePage.aspx it finds the ContentPlaceHolderControl,

<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder> /* defined in the master page */

/* inside SamplePage.aspx */
<ajaxtoolkit:tabcontainer runat="server" id="tabsmain" height="405px" Width="625px">
ContentPlaceHolder cph = (ContentPlaceHolder)this.Master.FindControl("ContentPlaceHolder1");
AjaxControlToolkit.TabContainer container = (AjaxControlToolkit.TabContainer)cph.FindControl("tabsmain");

whereas if I add it inside the base class I get this error:

Content controls have to be top-level controls in a content page or a nested master page that references a master page.

Is there a way I can get the ContentPlaceHolder inside my base class too? And how can I access it?

share|improve this question
 
There's no need for tags in titles. Please read meta.stackoverflow.com/q/19190/147072 for more information. –  Patrick Jun 7 at 11:58
add comment

3 Answers

Here is complete sample code how you can access ContentPlaceHolder:

First master code (Site1.master):

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="WebTesterInherit.Site1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

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

Now custom class that inherits from Page:

public class MyPage: System.Web.UI.Page
{

    public System.Web.UI.WebControls.ContentPlaceHolder GetMyContentPlaceHolder()
    {
        System.Web.UI.WebControls.ContentPlaceHolder holder = null;
        Site1 site = this.Master as Site1;
        if (site != null)
        {
            holder = site.FindControl("ContentPlaceHolder1") as System.Web.UI.WebControls.ContentPlaceHolder;
        }
        return holder;
    }
}

And finally page that inherits from MyPage (Default.aspx):

<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebTesterInherit.Default" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <asp:Button ID="btnTest" runat="server" Text="Test" OnClick="btnTest_Click"/><br />
    <asp:Label ID="lblMessage" runat="server" Text=""></asp:Label>
</asp:Content>

Code for Default.aspx:

public partial class Default : MyPage
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void btnTest_Click(object sender, EventArgs e)
    {
        try
        {
            System.Web.UI.WebControls.ContentPlaceHolder holder = base.GetMyContentPlaceHolder();
            lblMessage.Text = string.Format("Holder contains {0} control(s).", holder.Controls.Count);
        }
        catch (Exception ex)
        {
            lblMessage.Text = string.Format("Error: {0}", ex.Message);
        }
    }
}
share|improve this answer
add comment

I've checked and you can find a control nested in ContentPlaceHolder from base class OnLoad method.

Sure it can be done... but remember that some pages may have different controls in theirs CPH. Are you sure that you are in the context of a page which actually has tabsmain control?

I think if you have to do such things you have some design problem. A mix of master page and downward FindControl (base class -> derived class) just doesn't feel right.

share|improve this answer
add comment

Universal "search by id and type" method:

  protected T GetControlOfType<T>(Control root, string id) where T : Control {
    var stack = new Stack<Control>();
    stack.Push(root);
    while (stack.Count > 0) {
      var control = stack.Pop();
      var typedControl = control as T;
      if (typedControl != null && string.Compare(id, typedControl.ID, StringComparison.Ordinal) == 0) {
        return typedControl;
      }
      foreach (Control child in control.Controls) {
        stack.Push(child);
      }
    }
    return default(T);
  }

Usage:

   var control = GetControlOfType<MyControl>(Page, "MyControlServerID");
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.