简体   繁体   中英

Access child page controls from base page

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?

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);
        }
    }
}

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.

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");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM