C# ASP.Net FindControl 不工作 - 为什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/799655/
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
ASP.Net FindControl is not working - How come?
提问by LilMoke
I have used FindControl
in the past, prior to .NET 2.0/3.0. It seems like now, for some reason, the ID's of my controls get a funky named assigned. For example I assigned an id "cbSelect" to a checkbox, but FindControl does not find it. When I view the HTML it was assigned ctl00_bodyPlaceHolder_ctl02_cbSelect
.
我过去使用FindControl
过,在 .NET 2.0/3.0 之前。现在似乎出于某种原因,我的控件的 ID 获得了一个时髦的命名分配。例如,我为一个复选框分配了一个 id“cbSelect”,但 FindControl 没有找到它。当我查看它被分配的 HTML 时ctl00_bodyPlaceHolder_ctl02_cbSelect
。
I have not found one example of FindControl that mentions that. In fact everyone seems to just use find control like normal.
我还没有找到一个提到这一点的 FindControl 示例。事实上,每个人似乎都像平常一样使用 find 控件。
So, am I doing something wrong? Did .Net change? Can anyone shed some light onto this for me, it is really frustrating!
那么,我做错了什么吗?.Net 变了吗?谁能帮我解释一下,这真的很令人沮丧!
采纳答案by Aleris
You are probably using a MasterPage or user controls (ascx) and this is the reason the for client ids change. Imagine you have a control in the master page with the same id as one in the page. This would result in clashes. The id changes ensures all ClientID properties are unique on a page.
您可能正在使用 MasterPage 或用户控件 (ascx),这就是客户端 ID 更改的原因。假设您在母版页中有一个控件,其 ID 与页面中的控件相同。这会导致冲突。id 更改确保所有 ClientID 属性在页面上都是唯一的。
FindControl needs some special attention when working with MasterPages. Have a look at ASP.NET 2.0 MasterPages and FindControl(). The FindControl works inside a naming container. The MastePage and the page are different naming containers.
FindControl 在使用 MasterPages 时需要特别注意。看看ASP.NET 2.0 MasterPages 和 FindControl()。FindControl 在命名容器内工作。MastePage 和页面是不同的命名容器。
回答by Nick
When it's rendering the html, ASP.NET will prefix all the control IDs with the IDs of the naming containers (User Controls etc..) in a hierarchy going back all the way to the document root. This ensures that all the IDs are unique for post backs etc..
当它呈现 html 时,ASP.NET 会在所有控件 ID 前面加上命名容器(用户控件等)的 ID,层次结构一直追溯到文档根目录。这确保所有 ID 对于回发等都是唯一的。
This does not effect using FindControl where you should use the ID in the original markup.
这不会影响使用 FindControl,您应该在原始标记中使用 ID。
回答by George
Here is a reference as to how web form controls are named...
这是有关如何命名 Web 表单控件的参考...
回答by Stephen M. Redd
I've had pretty good luck working around this problem in "most" cases with a simple extension method
在“大多数”情况下,我很幸运地使用简单的扩展方法解决了这个问题
You can call it on whatever higher-level container control you think best, including the Page itself if you want to scan the entire control hierarchy.
您可以在您认为最好的任何更高级别的容器控件上调用它,如果您想扫描整个控件层次结构,包括 Page 本身。
private static Control FindControlIterative(this Control control, string id)
{
Control ctl = control;
LinkedList<Control> controls = new LinkedList<Control>();
while(ctl != null)
{
if(ctl.ID == id)
{
return ctl;
}
foreach(Control child in ctl.Controls)
{
if(child.ID == id)
{
return child;
}
if(child.HasControls())
{
controls.AddLast(child);
}
}
ctl = controls.First.Value;
controls.Remove(ctl);
}
return null;
}
回答by nemke
You could write extender to find any control on page using recursion. This could be in some Util/Helper class.
您可以编写扩展程序以使用递归查找页面上的任何控件。这可能在某些 Util/Helper 类中。
public static Control FindAnyControl(this Page page, string controlId)
{
return FindControlRecursive(controlId, page.Form);
}
public static Control FindAnyControl(this UserControl control, string controlId)
{
return FindControlRecursive(controlId, control);
}
public static Control FindControlRecursive(string controlId, Control parent)
{
foreach (Control control in parent.Controls)
{
Control result = FindControlRecursive(controlId, control);
if (result != null)
{
return result;
}
}
return parent.FindControl(controlId);
}
回答by George English
When searching for a control in a control collection, always use the id you assigned the control, not the one you see in the source post render. If FindControl() does not find the control you know exists, there is a good chance that you are not searching in the right branch of the control hierarchy. A recursive function has been successful for me.
在控件集合中搜索控件时,请始终使用您分配给控件的 ID,而不是您在源代码后期渲染中看到的 ID。如果 FindControl() 没有找到您知道存在的控件,则很有可能您没有在控件层次结构的正确分支中进行搜索。递归函数对我来说是成功的。
Here is my example of what I use for VB.NET 3.5:
这是我用于 VB.NET 3.5 的示例:
Function FindControlRecursive(ByVal ctrl As Control, ByVal id As String) As Control
Dim c As Control = Nothing
If ctrl.ID = id Then
c = ctrl
Else
For Each childCtrl In ctrl.Controls
Dim resCtrl As Control = FindControlRecursive(childCtrl, id)
If resCtrl IsNot Nothing Then c = resCtrl
Next
End If
Return c
End Function
Here is an example of how I would topically implement this function in my base page class:
下面是我将如何在我的基页类中局部实现此功能的示例:
Dim form HtmlForm = CType(FindControlRecursive(Me, "Form"), HtmlForm)
回答by Shawn Kovac
This is the VB.NET code that worked for me:
这是对我有用的 VB.NET 代码:
<Extension()> _
Function FindChildControlById(ByVal controlToStartWith As Control, ByVal controlIdToFind As String) As Control
If controlToStartWith Is Nothing Then Return Nothing
If controlToStartWith.ID = controlIdToFind Then Return controlToStartWith
For Each childControl As Control In controlToStartWith.Controls
Dim resCtrl As Control = FindChildControlById(childControl, controlIdToFind)
If resCtrl IsNot Nothing Then Return resCtrl
Next childControl
Return Nothing
End Function ' Function FindChildControlById(ByVal controlToStartWith As Control, ByVal controlIdToFind As String) As Control
Credit goes to George for the initial VB.NET code. I only modified it a teeny bit, with 2 functional change: mine doesn't error if/when null/Nothing is passed as the input control, and mine is implemented as an Extension. My other 3 minor changes don't affect the functionality, but to me, they were code simplifications. But I know it's very subjective.
最初的 VB.NET 代码归功于 George。我只修改了一点点,有 2 个功能更改:如果/当 null/Nothing 作为输入控件传递时,我的不会出错,并且我的作为扩展实现。我的其他 3 个小改动不会影响功能,但对我来说,它们是代码简化。但我知道这是非常主观的。
So this method can be used with:
所以这个方法可以用于:
Dim c1 As Control = Page.FindChildControlById("aspControlID")
And if you want to convert it into a specific child class of a Control, like this:
如果要将其转换为 Control 的特定子类,如下所示:
Dim c1 As Control = Page.FindChildControlById("aspControlID")
Dim c As HyperLink = TryCast(c1, HyperLink)
Update: My function is now named 'FindChildControlById' (previously was 'FindMiControl'). I liked SpeedNet's suggestion better.
更新:我的函数现在被命名为“FindChildControlById”(以前是“FindMiControl”)。我更喜欢 SpeedNet 的建议。