2009-04-08 78 views
8

我有一个嵌套2级的母版页。它有一个母版页,该母版页有一个母版页。查找嵌套主页内的控件

当我坚持控制在名为“BCR”一个的ContentPlaceHolder - 我必须要找到控制像这样:

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

我完全失去了什么?或者这是如何完成的?

我即将使用一个MultiView,它是一个有条件的内容控件。所以如果我想改变看法,我必须得到对该控制权的参考?获得该参考将会更加棘手!有没有更好的办法?

谢谢

回答

4

首先,你应该知道,MasterPages实际上坐在页面内。以至于在ASPX的Load事件之后实际调用MasterPage的Load事件。

这意味着,页面对象实际上是控件层次结构中的最高控件。

因此,了解这一点,在这样的嵌套环境中找到任何控件的最佳方法是编写一个递归函数,循环遍历每个控件和子控件,直到找到您要找的控件和子控件。在这种情况下,您的MasterPages实际上是主页控件的子控件。

您可以从任何像这样的控制中得到的主要Page对象:

C#:

this.Page;

VB.NET

Me.Page

我发现,通常情况下,控制的类的FindControl()方法是很没用,因为环境总是嵌套。

因为如果这样,我决定使用.NET 3.5的新扩展功能来扩展Control类。

通过使用下面的代码(VB.NET),在说,你AppCode文件夹,所有控件现在将通过调用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 
22

寻找控制是一种痛苦,和我已经使用了这种方法,这是我从CodingHorror blog了相当长一段时间前,如果用一个空的ID在通过了返回null单修改。

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

在你的情况,我认为你需要如下:

Label lblName = (Label) FindControlRecursive(Page, "lblName"); 

使用这种方法通常要方便得多,因为您不需要确切地知道控件所处的位置(当然,假设您知道ID),但是如果您使用嵌套控件同名,你可能会有一些奇怪的行为,所以这可能是值得注意的。

+0

这很好用。谢谢。 – 2010-10-17 22:27:05

+0

+1谢谢,这也帮我出了 – leen3o 2010-12-02 10:03:08

4

尽管我喜欢递归,并且同意安迪和门,但是您可能要考虑的另一种方法是使用strongly typed Master page。你所要做的就是在你的aspx页面中添加一条指令。

不要从主页面访问页面的控件,而应考虑从页面本身访问母版页中的控件。当您的母版页上有标题标签并且想要从使用母版的每个页面设置其值时,此方法非常有意义。

我不是100%确定的,但我认为这将是嵌套母版页更简单的技巧,因为您只需将VirtualPath指向包含您希望访问的控件的主文件。如果你想要访问两个控件,每个相应的母版页都可以访问它,但这可能证明是棘手的。

1

我已经使用了<%@ MasterType VirtualPath="~/MyMaster.master" %>方法。我在主母版页中有一个属性,然后在详细母版页中具有相同名称的其他属性调用主主属性,并且它工作正常。

我有这样的主母版页

public string MensajeErrorString 
    { 
     set 
     { 
      if (value != string.Empty) 
      { 
       MensajeError.Visible = true; 
       MensajeError.InnerHtml = value; 
      } 
      else 
       MensajeError.Visible = false; 
     } 


    } 

这仅仅是要显示错误消息的div元素。我想在具有详细母版页的页面中使用这个相同的属性(这与主要母版嵌套)。

那么在细节主我有这个

public string MensajeErrorString 
    { 
     set 
     { 
       Master.MensajeErrorString = value; 
     } 

    } 

林调用从细节主主主属性创建相同的行为。

0

我刚刚完成了它的工作。

在contentpage.aspx,我写了下面:

If Master.Master.connectsession.IsConnected Then my coded comes in here End If

2

这里是一个更通用的,具有自定义条件工作的代码(可以是一个lambda表达式!)

呼叫:

Control founded = parent.FindControl(c => c.ID == "youdId", true); 

控制扩展

public static class ControlExtensions 
{ 
    public static Control FindControl(this Control parent, Func<Control, bool> condition, bool recurse) 
    { 
     Control founded = null; 
     Func<Control, bool> search = null; 
     search = c => c != parent && condition(c) ? (founded = c) != null : 
                recurse ? c.Controls.FirstOrDefault(search) != null : 
                (founded = c.Controls.FirstOrDefault(condition)) != null; 
     search(parent); 
     return founded; 
    } 
}