FindControl 和 INamingContainer

Posted

技术标签:

【中文标题】FindControl 和 INamingContainer【英文标题】:FindControl and INamingContainer 【发布时间】:2011-12-31 02:53:42 【问题描述】:

我想谨慎地提出这个问题,所以乐于助人的人不要插手告诉我我已经知道的信息(我不想浪费他们的时间)。

我想了解 FindControl 在 ASP.NET Web 应用程序项目(其中 c# 文件在标记中被引用为 CodeBehind,而不是 CodeFile)中的工作原理。

代码后面有两个文件位于标记文件之间。例如。 Default.aspx 会有 Default.aspx.cs 和 Default.aspx.designer.cs

如果您在页面上放置一个按钮,它将被添加到设计器文件中。例如: 受保护的全局::System.Web.UI.WebControls.LinkBut​​ton LinkBut​​ton1;

如果您想获得对该控件的引用,它可以立即作为 Default 类的成员使用。例如。 this.LinkBut​​ton1.Text = "点击我";

如果您查看页面的跟踪,则会根据 INamingContainers(此处为页面)的行为为它提供一个唯一 ID:ctl00$ContentPlaceHolder1$LinkBut​​ton1

我不明白的是为什么语句返回 null: 控件 c = Page.FindControl("LinkBut​​ton1");

我意识到这是不必要的,因为默认类已经可以使用该按钮。这是因为它在 Default.aspx.designer.cs 文件中显示为成员。

我不明白的是为什么返回null。因为 Page 实现了 INamingContainer,并且按钮的 ID 与 INamingContainer 中控件的预期 ID 相关。这不正是 FindControl 发现的那种东西吗?

【问题讨论】:

【参考方案1】:

这种行为对我来说是新的,可能是因为我不会尝试搜索无论如何都可以直接访问的控件。我认为这也可能是 ASP.NET 甚至不允许这样做的原因,因为使用现有引用比找到它(或不找到它)更快、更安全。

FindControl 方法可用于访问 ID 不是 在设计时可用。该方法只搜索页面的 直接或***容器;它不会递归搜索 页面上包含的命名容器中的控件。访问 子命名容器中的控件,调用 FindControl 该容器的方法。

http://msdn.microsoft.com/en-us/library/31hxzsdw.aspx

编辑:检查此行为后,我注意到 null 仅在使用 MasterPage 的页面上时才会返回,因为页面的 ControlCollection 中的唯一控件是 MasterPage本身。 这就说得通了。当控件位于具有 MasterPage 的页面的顶层时,您不能保证 ID 是唯一的,因为其他 ContentPage 也可能具有具有此 ID 的控件,而 FindControl 今天可能会返回另一个控件而不是明天。

如果您查看要查找的控件的NamingContainer,您会发现在MasterPage 的情况下是ContentPlaceHolder,在“正常”页面的情况下是页面本身。

所以在通过 FindControl 找到控件之前,您需要先获取 MasterPage 的 ContentPlaceholder 的引用:

Page.Master.FindControl("ContentPlaceHolder1").FindControl("LinkButton1");

http://msdn.microsoft.com/en-us/library/xxwa0ff0.aspx

【讨论】:

嗨蒂姆,你是对的。如果我将语句修改为Control c = this.Master.FindControl("ContentPlaceHolder1").FindControl("LinkButton1");,它确实找到了控件。对我不小心。但我同意。我总是会使用现成的财产。这只是一种好奇。干杯【参考方案2】:

FindControl 不是递归的,看起来你有一个中介 ContentPlaceHolder1 控件,它是一个命名容器,所以这应该可以工作:Page.FindControl("ContentPlaceHolder1").FindControl("LinkButton1")

【讨论】:

这不起作用,因为Page.FindControl("ContentPlaceHolder1") 返回null。您必须先参考母版页。

以上是关于FindControl 和 INamingContainer的主要内容,如果未能解决你的问题,请参考以下文章

FormView.FindControl() 在 DataBind() 之前返回 null

在面板内的控件上使用 FindControl() 返回 null

FindControl() 返回空值

C#,FindControl [重复]

ASP.NET GridView 在 BoundField 上使用 FindControl() 来操作字段

FindControl的使用方法