ASP.Net FindControl不工作 - 怎么样?

时间:2009-04-28 20:21:21

标签: c# .net asp.net findcontrol

我以前在.NET 2.0 / 3.0之前使用过FindControl。现在看来,由于某些原因,我的控件的ID会被分配一个时髦的名字。例如,我为复选框分配了一个id“cbSelect”,但FindControl找不到它。当我查看HTML时,它被分配了ctl00_bodyPlaceHolder_ctl02_cbSelect

我还没有找到一个提到它的FindControl示例。事实上,每个人似乎只是像正常一样使用find控件。

那么,我做错了吗? .Net改变了吗?任何人都可以为我阐明这一点,这真的令人沮丧!

7 个答案:

答案 0 :(得分:29)

您可能正在使用MasterPage或用户控件(ascx),这就是客户ID更改的原因。想象一下,您在母版页中有一个控件,其ID与页面中的控件相同。这会导致冲突。 id更改确保所有ClientID属性在页面上都是唯一的。

使用MasterPages时,FindControl需要特别注意。看看ASP.NET 2.0 MasterPages and FindControl()。 FindControl在naming container内部工作。 MastePage和页面是不同的命名容器。

答案 1 :(得分:8)

通过简单的扩展方法

,我在“大多数”案例中解决了这个问题

您可以在您认为最好的任何更高级别的容器控件上调用它,包括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;
}

答案 2 :(得分:8)

您可以编写扩展程序以使用递归在页面上查找任何控件。 这可能在某些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);
    }

答案 3 :(得分:7)

在控件集合中搜索控件时,请始终使用您为控件分配的ID,而不是您在源文章渲染中看到的ID。如果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)

答案 4 :(得分:3)

这是适用于我的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代码归功于George。我只修改了一小部分,有2个功能改变:如果/当null / Nothing作为输入控件传递时我的没有错误,并且我的实现为扩展。我的其他3个小改动不会影响功能,但对我来说,它们是代码简化。但我知道这是非常主观的。

所以这个方法可以用于:

Dim c1 As Control = Page.FindChildControlById("aspControlID")

如果您想将其转换为Control的特定子类,请执行以下操作:

Dim c1 As Control = Page.FindChildControlById("aspControlID")
Dim c As HyperLink = TryCast(c1, HyperLink)

更新:我的函数现在命名为'FindChildControlById'(以前是'FindMiControl')。我更喜欢SpeedNet的建议。

答案 5 :(得分:1)

当它呈现html时,ASP.NET将在所有控件ID前面加上命名容器(用户控件等)的ID,这些ID在层次结构中一直返回到文档根目录。这可确保所有ID对于回发等都是唯一的。

使用FindControl不会影响原始标记中的ID。

答案 6 :(得分:0)

以下是关于如何命名Web表单控件的参考...

Web Forms Control Identification