How to conveniently access a control within a nested master page?
Accessing master page controls is usually straight forward:
Dim ddl As DropDownList = Master.FindControl("ddl")
However when my setup is as follows the control cannot be found, presumably becuase the control is within a content
block:
1 Root Master
<asp:ContentPlaceHolder ID="cphMainContent" runat="server" />
2 Nested Master
<%@ Master Language="VB" MasterPageFile="~/Root.master" AutoEventWireup="false" CodeFile="Nested.master.vb" Inherits="Nested" %>
<asp:Content ID="MainContent" ContentPlaceHolderID="cphMainContent" runat="server">
<asp:DropDownList ID="ddl" runat="server" DataTextField="Text" DataValueField="ID"/>
</asp:Content>
3 Content Page VB.NET
Dim ddl As DropDownList = Master.FindControl("ddl")
Workaround
I have found a solution by traversing up the tree finding the root content placeholder cphMainContent
and then looking for the control within.
cphMainContent = CType(Master.Master.FindControl("cphMainContent"), ContentPlaceHolder)
Dim ddl As DropDownList = cphMainContent .FindControl("ddl")
However this solution seems very roundabout and inefficient.
Can the control be accessed directly from within the content
block of the master page?
Here is an extension method that can handle an arbitrary number of nesting levels:
public static class PageExtensions
{
/// <summary>
/// Recursively searches this MasterPage and its parents until it either finds a control with the given ID or
/// runs out of parent masters to search.
/// </summary>
/// <param name="master">The first master to search.</param>
/// <param name="id">The ID of the control to find.</param>
/// <returns>The first control discovered with the given ID in a MasterPage or null if it's not found.</returns>
public static Control FindInMasters(this MasterPage master, string id)
{
if (master == null)
{
// We've reached the end of the nested MasterPages.
return null;
}
else
{
Control control = master.FindControl(id);
if (control != null)
{
// Found it!
return control;
}
else
{
// Search further.
return master.Master.FindInMasters(id);
}
}
}
}
Use the extension method from any class inheriting from System.Web.UI.Page like so:
DropDownList ddl = (DropDownList)Page.Master.FindInMasters("ddl");
if (ddl != null)
{
// do things
}