私は複雑なasp.netフォームを持っており、1つのフォームに50から60のフィールドがありMultiview
、MultiView内GridView
にはCheckBoxes
.
現在、メソッドのチェーンを使用しFindControl()
て子 ID を取得しています。
さて、私の質問は、ASP.NET でネストされたコントロールを見つける他の方法/解決策があるということです。
私は複雑なasp.netフォームを持っており、1つのフォームに50から60のフィールドがありMultiview
、MultiView内GridView
にはCheckBoxes
.
現在、メソッドのチェーンを使用しFindControl()
て子 ID を取得しています。
さて、私の質問は、ASP.NET でネストされたコントロールを見つける他の方法/解決策があるということです。
特定のタイプのコントロールを探している場合は、次のような再帰ループを使用できます - 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);
}
}
}
}
いつものように遅く。誰かがまだこれに興味を持っているなら、関連する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;
}
}
}
}
強調表示されているソリューションはすべて再帰を使用しています (これはパフォーマンスにコストがかかります)。再帰のないよりクリーンな方法は次のとおりです。
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);
}
FindControlは、ネストされたコントロール内を再帰的に検索しません。これは、 NamigContainerが FindControl を呼び出しているコントロールであるコントロールのみを検索します。
デフォルトでは、ASP.Net がネストされたコントロールを再帰的に調べないのには理由があります。
再利用性の理由から、GridViews、Formviews、UserControls などを他の UserControls 内にカプセル化することを検討してください。ページにすべてのロジックを実装し、再帰ループでこれらのコントロールにアクセスした場合、それをリファクタリングするのは非常に困難です。イベント ハンドラー (GridView の RowDataBound) を介してロジックとアクセス メソッドを実装した場合は、はるかに単純になり、エラーが発生しにくくなります。
コントロール辞書を作成することにしました。保守が難しく、再帰的な 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: はい、最初から検索する必要はありません。すでに存在することを知っているものを検索する必要はありません。既知のオブジェクトを参照できるシステムを構築することをお勧めします。
基底クラスに以下のクラスを作成します。クラス すべてのコントロールを取得するには:
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;
}
}
}
}
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;
}