Search code examples
c#asp.net.net-3.5master-pages

Finding controls inside nested master pages


I have a master page which is nested 2 levels. It has a master page, and that master page has a master page.

When I stick controls in a ContentPlaceHolder with the name "bcr" - I have to find the controls like so:

 Label lblName =(Label)Master.Master.FindControl("bcr").FindControl("bcr").FindControl("Conditional1").FindControl("ctl03").FindControl("lblName");

Am I totally lost? Or is this how it needs to be done?

I am about to work with a MultiView, which is inside of a conditional content control. So if I want to change the view I have to get a reference to that control right? Getting that reference is going to be even nastier! Is there a better way?

Thanks


Solution

  • Firstly, you should know that MasterPages actually sit inside Pages. So much so that a MasterPage's Load event is actually called after your ASPX's Load event.

    This means, the Page object is actually the highest control in the control hierarchy.

    So, knowing this, the best way to find any control in such a nested environment, is to write a recursive function that loops through every control and child controls until it finds the one you're looking for. in this case, your MasterPages are actually child controls of the main Page control.

    You get to the main Page object from inside any control like this:

    C#:

    this.Page;

    VB.NET

    Me.Page

    I find that usually, the Control's class FindControl() method is pretty useless, as the enviroment is always nested.

    Because if this, I've decided to use .NET's 3.5 new Extension features to extend the Control class.

    By using the code below (VB.NET), in say, your AppCode folder, all your controls will now peform a recursive find by calling FindByControlID()

        Public Module ControlExtensions
        <System.Runtime.CompilerServices.Extension()> _
        Public Function FindControlByID(ByRef SourceControl As Control, ByRef ControlID As String) As Control
            If Not String.IsNullOrEmpty(ControlID) Then
                Return FindControlHelper(Of Control)(SourceControl.Controls, ControlID)
            Else
                Return Nothing
            End If
        End Function
    
        Private Function FindControlHelper(Of GenericControlType)(ByVal ConCol As ControlCollection, ByRef ControlID As String) As Control
            Dim RetControl As Control
    
            For Each Con As Control In ConCol
                If ControlID IsNot Nothing Then
                    If Con.ID = ControlID Then
                        Return Con
                    End If
                Else
                    If TypeOf Con Is GenericControlType Then
                        Return Con
                    End If
                End If
    
                If Con.HasControls Then
                    If ControlID IsNot Nothing Then
                        RetControl = FindControlByID(Con, ControlID)
                    Else
                        RetControl = FindControlByType(Of GenericControlType)(Con)
                    End If
    
                    If RetControl IsNot Nothing Then
                        Return RetControl
                    End If
                End If
            Next
    
            Return Nothing
        End Function
    
    End Module