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
Finding controls is a pain, and I've been using this method which I got from the CodingHorror blog quite a while ago, with a single modification that returns null if an empty id is passed in.
/// <summary>
/// Recursive FindControl method, to search a control and all child
/// controls for a control with the specified ID.
/// </summary>
/// <returns>Control if found or null</returns>
public static Control FindControlRecursive(Control root, string id)
{
if (id == string.Empty)
return null;
if (root.ID == id)
return root;
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
In your case, I think you'd need the following:
Label lblName = (Label) FindControlRecursive(Page, "lblName");
Using this method is generally much more convenient, as you don't need to know exactly where the control resides to find it (assuming you know the ID, of course), though if you have nested controls with the same name, you'll probably get some strange behavior, so that might be something to watch out for.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With