ASP.Net FindControl不工作 - 怎么回事?
我在.NET 2.0/3.0之前的版本中使用过FindControl
。现在看来,出于某种原因,我的控件的ID得到了一个名为分配的时髦。例如,我将一个id“cbSelect”分配给一个复选框,但FindControl没有找到它。当我查看HTML时,它被分配为ctl00_bodyPlaceHolder_ctl02_cbSelect
。ASP.Net FindControl不工作 - 怎么回事?
我还没有找到一个FindControl的例子提到。实际上,每个人似乎都只是使用像普通的查找控制。
那么,我做错了什么? .Net是否改变?任何人都可以为我阐明这一点,这真是令人沮丧!
您可能正在使用MasterPage或用户控件(ascx),这就是客户端id更改的原因。想象一下,您在母版页中使用与页面中相同的ID进行控制。这会导致冲突。 id更改确保所有ClientID属性在页面上都是唯一的。
使用MasterPages时,FindControl需要特别注意。看看ASP.NET 2.0 MasterPages and FindControl()。 FindControl在naming container内工作。 MastePage和页面是不同的命名容器。
当它呈现html时,ASP.NET会将所有控件ID与命名容器(用户控件等)的ID作为前缀一直回溯到文档根目录。这确保了所有ID对于后贴等都是唯一的。
这不影响使用FindControl,您应该在原始标记中使用ID。
我有运气还算不错解决此问题,工作中“最”的情况下用一个简单的扩展方法
你可以在任何你认为最好的高级容器控件上调用它,包括如果你想扫描整个控件层次结构的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;
}
您可以使用递归来编写扩展器以查找页面上的任何控件。 这可能在某些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);
}
在控件集合中搜索控件时,请始终使用您分配给控件的标识,而不是在源标记呈现中看到的标识。如果FindControl()没有找到你知道存在的控件,那么很有可能你没有在控件层次结构的右边分支中搜索。递归函数对我来说是成功的。
这里是我的就是我使用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
这里是我怎么会在局部我的基地页类实现这个功能的例子:
Dim form HtmlForm = CType(FindControlRecursive(Me, "Form"), HtmlForm)
+1,因为没有看到你的我已经在C#中用相同的方法实现它: ``````````空值; if(ctl.ID == id)return ctl; (ctl.Controls.Count> 0) foreach(ctl.Controls中的Control sc) 控制fnd = FindControlRecursive(sc,id); if(fnd!= null)return fnd; } return null; }` – gkakas 2013-11-17 10:04:55
这是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
信用去乔治最初的VB.NET代码。我只修改它少许,有2个功能改变:如果/当null /没有任何东西作为输入控件传递时,我的错误不会发生错误,并且我的作为扩展实现。我的其他3个较小的更改不影响功能,但对我来说,它们是代码简化。但我知道这很主观。
那么这种方法可以用于:
Dim c1 As Control = Page.FindChildControlById("aspControlID")
如果你想将它转换成一个特定的子类控制的,就像这样:
Dim c1 As Control = Page.FindChildControlById("aspControlID")
Dim c As HyperLink = TryCast(c1, HyperLink)
更新:我的功能现在名为'FindChildControlById'(以前是'FindMiControl')。我更喜欢SpeedNet的建议。
微软实施这个的方式是这样的一个笑话,它应该只是工作。哦,你有一个主页?大约500个嵌套母版页如何?该方法应该算出来,并且找到控制周期的必要条件。 – 2013-05-19 01:51:19
你知道你在同一个想法中使用“应该”和“微软”吗? – user1566694 2016-12-13 20:32:28