48

私は複雑なasp.netフォームを持っており、1つのフォームに50から60のフィールドがありMultiview、MultiView内GridViewにはCheckBoxes.

現在、メソッドのチェーンを使用しFindControl()て子 ID を取得しています。

さて、私の質問は、ASP.NET でネストされたコントロールを見つける他の方法/解決策があるということです。

4

9 に答える 9

72

特定のタイプのコントロールを探している場合は、次のような再帰ループを使用できます - http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol-recursive-with -generics.aspx

これは、指定されたタイプのすべてのコントロールを返す私が作成した例です

/// <summary>
/// Finds all controls of type T stores them in FoundControls
/// </summary>
/// <typeparam name="T"></typeparam>
private class ControlFinder<T> where T : Control 
{
    private readonly List<T> _foundControls = new List<T>();
    public IEnumerable<T> FoundControls
    {
        get { return _foundControls; }
    }    

    public void FindChildControlsRecursive(Control control)
    {
        foreach (Control childControl in control.Controls)
        {
            if (childControl.GetType() == typeof(T))
            {
                _foundControls.Add((T)childControl);
            }
            else
            {
                FindChildControlsRecursive(childControl);
            }
        }
    }
}
于 2011-02-10T10:19:38.727 に答える
19

いつものように遅く。誰かがまだこれに興味を持っているなら、関連するSOの質問回答がたくさんあります。これを解決するための再帰的拡張メソッドの私のバージョン:

public static IEnumerable<T> FindControlsOfType<T>(this Control parent)
                                                        where T : Control
{
    foreach (Control child in parent.Controls)
    {
        if (child is T)
        {
            yield return (T)child;
        }
        else if (child.Controls.Count > 0)
        {
            foreach (T grandChild in child.FindControlsOfType<T>())
            {
                yield return grandChild;
            }
        }
    }
}
于 2011-12-08T03:11:08.223 に答える
12

強調表示されているソリューションはすべて再帰を使用しています (これはパフォーマンスにコストがかかります)。再帰のないよりクリーンな方法は次のとおりです。

public T GetControlByType<T>(Control root, Func<T, bool> predicate = null) where T : Control 
{
    if (root == null) {
        throw new ArgumentNullException("root");
    }

    var stack = new Stack<Control>(new Control[] { root });

    while (stack.Count > 0) {
        var control = stack.Pop();
        T match = control as T;

        if (match != null && (predicate == null || predicate(match))) {
            return match;
        }

        foreach (Control childControl in control.Controls) {
           stack.Push(childControl);
        }
    }

    return default(T);
}
于 2015-09-04T13:19:51.517 に答える
6

FindControlは、ネストされたコントロール内を再帰的に検索しません。これは、 NamigContainerが FindControl を呼び出しているコントロールであるコントロールのみを検索します。

デフォルトでは、ASP.Net がネストされたコントロールを再帰的に調べないのには理由があります。

  • パフォーマンス
  • エラーの回避
  • 再利用性

再利用性の理由から、GridViews、Formviews、UserControls などを他の UserControls 内にカプセル化することを検討してください。ページにすべてのロジックを実装し、再帰ループでこれらのコントロールにアクセスした場合、それをリファクタリングするのは非常に困難です。イベント ハンドラー (GridView の RowDataBound) を介してロジックとアクセス メソッドを実装した場合は、はるかに単純になり、エラーが発生しにくくなります。

于 2011-02-10T10:57:00.060 に答える
1

コントロール辞書を作成することにしました。保守が難しく、再帰的な FindControl() よりも高速に実行される可能性があります。

protected void Page_Load(object sender, EventArgs e)
{
  this.BuildControlDics();
}

private void BuildControlDics()
{
  _Divs = new Dictionary<MyEnum, HtmlContainerControl>();
  _Divs.Add(MyEnum.One, this.divOne);
  _Divs.Add(MyEnum.Two, this.divTwo);
  _Divs.Add(MyEnum.Three, this.divThree);

}

そして、OPの質問に答えなかったために親指を立てる前に...

Q: 私の質問は、ASP.NET でネストされたコントロールを見つける他の方法/解決策はありますか? A: はい、最初から検索する必要はありません。すでに存在することを知っているものを検索する必要はありません。既知のオブジェクトを参照できるシステムを構築することをお勧めします。

于 2015-11-13T19:45:28.253 に答える
1

コントロールのアクション管理

基底クラスに以下のクラスを作成します。クラス すべてのコントロールを取得するには:

public static class ControlExtensions
{
    public static IEnumerable<T> GetAllControlsOfType<T>(this Control parent) where T : Control
    {
        var result = new List<T>();
        foreach (Control control in parent.Controls)
        {
            if (control is T)
            {
                result.Add((T)control);
            }
            if (control.HasControls())
            {
                result.AddRange(control.GetAllControlsOfType<T>());
            }
        }
        return result;
    }
}

データベースから: すべてのアクション ID (divAction1、divAction2 .... など) を取得し、DATASET (DTActions) で動的に特定のユーザーを許可します。

Aspx の場合: HTML では、アクション (ボタン、アンカーなど) を div または span に配置し、次のような ID を付けます。

<div id="divAction1" visible="false" runat="server" clientidmode="Static">   
                <a id="anchorAction" runat="server">Submit
                        </a>                      
                 </div>

CS の場合: ページで次の機能を使用します。

private void ShowHideActions()
    {

        var controls = Page.GetAllControlsOfType<HtmlGenericControl>();

        foreach (DataRow dr in DTActions.Rows)
        {          

            foreach (Control cont in controls)
            {

                if (cont.ClientID == "divAction" + dr["ActionID"].ToString())
                {
                    cont.Visible = true;
                }

            }
        }
    }
于 2015-04-07T18:54:22.927 に答える
1

https://blog.codinghorror.com/recursive-pagefindcontrol/

Page.FindControl("DataList1:_ctl0:TextBox3");

また

private Control FindControlRecursive(Control root, string id)
{
    if (root.ID == id)
    {
        return root;
    }
    foreach (Control c in root.Controls)
    {
        Control t = FindControlRecursive(c, id);
        if (t != null)
        {
            return t;
        }
    }
    return null;
}
于 2020-03-11T15:33:28.590 に答える