29

FindControl.NET 2.0/3.0 より前に、過去に使用したことがあります。何らかの理由で、コントロールの ID にファンキーな名前が割り当てられているようです。たとえば、ID「cbSelect」をチェックボックスに割り当てましたが、FindControl はそれを見つけられません。HTML を表示すると、割り当てられましctl00_bodyPlaceHolder_ctl02_cbSelectた。

それについて言及している FindControl の例は 1 つも見つかりませんでした。実際、誰もが通常どおり検索コントロールを使用しているようです。

それで、私は何か間違ったことをしていますか?.Net は変更されましたか? 誰かが私のためにこれに光を当てることができますか、それは本当にイライラします!

4

7 に答える 7

29

おそらく、MasterPage またはユーザー コントロール (ascx) を使用しており、これがクライアント ID の変更の理由です。マスター ページに、ページ内のコントロールと同じ ID を持つコントロールがあるとします。これにより、衝突が発生します。ID の変更により、すべての ClientID プロパティがページ上で一意になります。

MasterPages を操作する場合、FindControl には特別な注意が必要です。ASP.NET 2.0 MasterPages と FindControl() を見てください。FindControl は名前付けコンテナー内で機能します。MastePage とページは異なるネーミング コンテナーです。

于 2009-04-28T20:30:20.087 に答える
10

再帰を使用してページ上の任意のコントロールを見つけるためにエクステンダーを作成できます。これは 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);
    }
于 2010-01-27T13:51:48.123 に答える
8

単純な拡張メソッドを使用して、「ほとんどの」ケースでこの問題を回避することができました。

コントロール階層全体をスキャンする場合は、ページ自体を含め、最適と思われる上位レベルのコンテナー コントロールで呼び出すことができます。

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;
}
于 2009-04-28T20:56:22.707 に答える
7

コントロールコレクションでコントロールを検索するときは、ソースのポストレンダリングに表示されるIDではなく、常にコントロールに割り当てたIDを使用してください。FindControl()が、存在することがわかっているコントロールを見つけられない場合は、コントロール階層の右側のブランチを検索していない可能性があります。再帰関数は私にとって成功しています。

これが私がVB.NET3.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)
于 2010-03-02T20:57:02.197 に答える
1

HTML をレンダリングするとき、ASP.NET はすべてのコントロール ID の前に名前付けコンテナー (ユーザー コントロールなど) の ID を付けて、ドキュメント ルートまでさかのぼります。これにより、すべての ID がポストバックなどで一意になります。

これは、元のマークアップで ID を使用する必要がある FindControl の使用には影響しません。

于 2009-04-28T20:31:37.713 に答える
0

これは、Web フォーム コントロールの命名方法に関するリファレンスです...

Web フォーム コントロールの識別

于 2009-04-28T20:32:37.930 に答える