C# 在嵌套母版页中查找控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/728168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:45:46  来源:igfitidea点击:

Finding controls inside nested master pages

c#asp.net.net-3.5master-pages

提问by user53885

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

我有一个嵌套 2 级的母版页。它有一个母版页,该母版页有一个母版页。

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

当我将控件粘贴在名为“bcr”的 ContentPlaceHolder 中时 - 我必须像这样找到控件:

 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?

我即将使用 MultiView,它位于条件内容控件内。因此,如果我想更改视图,我必须获得对该控件的引用,对吗?获得该参考将更加令人讨厌!有没有更好的办法?

Thanks

谢谢

采纳答案by andy

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.

首先,您应该知道 MasterPages 实际上位于 Pages 内。以至于 MasterPage 的 Load 事件实际上是在 ASPX 的 Load 事件之后调用的。

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

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

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.

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

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

您可以从任何控件内部访问主 Page 对象,如下所示:

C#:

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.

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

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

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

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

通过使用下面的代码 (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

回答by Mun

Finding controls is a pain, and I've been using this method which I got from the CodingHorror blogquite a while ago, with a single modification that returns null if an empty id is passed in.

寻找控件是一件痛苦的事情,我很久以前就一直在使用我从CodingHorror 博客中得到的这个方法,如果传入一个空的 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;
}

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.

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

回答by Aaron Daniels

Although I love recursion, and agree with andy and Mun, one other approach you may want to consider is to have a strongly typed Master page. All you have to do is add one directive in your aspx page.

尽管我喜欢递归,并且同意 andy 和 Mun 的观点,但您可能要考虑的另一种方法是使用强类型母版页。您所要做的就是在您的 aspx 页面中添加一个指令。

Instead of accessing a page's control from your master page, consider accessing a control in your master page from the page itself. This approach makes a lot of sense when you have a header label on your master page, and want to set its value from each page that uses the master.

与其从母版页访问页面控件,不如考虑从页面本身访问母版页中的控件。当您的母版页上有标题标签,并希望从使用母版的每个页面设置其值时,这种方法很有意义。

I'm not 100% sure, but I think this would be simpler technique with nested master pages, as you would just point the VirtualPath to the master containing the control you wish to access. It might prove to be tricky though if you want to access two controls, one in each respective master page.

我不是 100% 确定,但我认为这将是嵌套母版页的更简单技术,因为您只需将 VirtualPath 指向包含您希望访问的控件的母版。如果您想访问两个控件,每个控件在各自的母版页中,这可能会被证明是棘手的。

回答by Juan

I have used the <%@ MasterType VirtualPath="~/MyMaster.master" %>method. I have a property in the main master page then in the detail master page other property with the same name calling the main master property and it works fine.

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

I have this in the main master page

我在主母版页中有这个

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


    }

this is just a div element that have to show an error message. I would like to use this same property in the pages with the detail master page(this is nested with the main master).

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

Then in the detail master I have this

然后在细节大师我有这个

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

    }

Im calling the main master property from the detail master to create the same behavior.

我从细节大师调用主要的主属性来创建相同的行为。

回答by ebot64

I just got it working perfectly.

我刚刚让它完美运行。

In contentpage.aspx, I wrote the following:

在 contentpage.aspx 中,我写了以下内容:

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

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

回答by Raevean

Here is a code that is more generic and works with a custom condition (that can be a lambda expression!)

这是一个更通用的代码,适用于自定义条件(可以是 lambda 表达式!)

Call:

称呼:

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

Control extension

控制扩展

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