webentwicklung-frage-antwort-db.com.de

Besserer Weg, um die Kontrolle in ASP.NET zu finden

Ich habe ein komplexes asp.net-Formular mit sogar 50 bis 60 Feldern in einem Formular, als gäbe es Multiview, in MultiView habe ich ein GridView und in GridView habe ich mehrere CheckBoxes ] _.

Derzeit verwende ich die Verkettung der FindControl() -Methode und das Abrufen der untergeordneten ID.

Nun ist meine Frage, dass es eine andere Möglichkeit/Lösung gibt, das verschachtelte Steuerelement in ASP.NET zu finden.

46
santosh singh

Wenn Sie nach einer bestimmten Art von Steuerelement suchen, können Sie eine rekursive Schleife wie diese verwenden - http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol) -recursive-with-generics.aspx

Hier ist ein Beispiel, das ich erstellt habe und das alle Steuerelemente des angegebenen Typs zurückgibt

/// <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);
            }
        }
    }
}
72
jimmystormig

Spät wie immer. Wenn sich noch jemand dafür interessiert, gibt es eine Reihe von verwandten SO Fragen und Antworten . Meine Version der rekursiven Erweiterungsmethode zur Lösung dieses Problems :

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;
            }
        }
    }
}
17
David Clarke

Bei allen hervorgehobenen Lösungen wird eine Rekursion verwendet (was die Leistung beeinträchtigt). Hier ist sauberer Weg ohne Rekursion:

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);
}
9
Ondrej Svejdar

FindControl sucht nicht rekursiv in verschachtelten Steuerelementen. Es werden nur Steuerelemente gefunden, die NamigContainer das Steuerelement sind, für das Sie FindControl aufrufen.

Es gibt einen Grund, warum ASP.Net Ihre verschachtelten Steuerelemente standardmäßig nicht rekursiv untersucht:

  • Performance
  • Fehler vermeiden
  • Wiederverwendbarkeit

Stellen Sie sich vor, Sie möchten Ihre GridViews, Formviews, UserControls usw. aus Gründen der Wiederverwendbarkeit in andere UserControls einbetten. Wenn Sie die gesamte Logik in Ihre Seite implementiert hätten und mit rekursiven Schleifen auf diese Steuerelemente zugegriffen hätten, wäre es sehr schwierig, dies umzugestalten. Wenn Sie Ihre Logik und Zugriffsmethoden über die Event-Handler (z. B. RowDataBound von GridView) implementiert haben, ist dies viel einfacher und weniger fehleranfällig.

6
Tim Schmelter

Ich habe mich entschieden, nur Steuerelementwörterbücher zu erstellen. Schwieriger zu warten, läuft möglicherweise schneller als das rekursive 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);

}

Und bevor ich die Daumen runter bekomme, weil ich die Frage des OP nicht beantwortet habe ...

F: Meine Frage ist nun, ob es eine andere Möglichkeit/Lösung gibt, das verschachtelte Steuerelement in ASP.NET zu finden. A: Ja, vermeiden Sie die Notwendigkeit, zuerst nach ihnen zu suchen. Warum nach Dingen suchen, von denen Sie bereits wissen, dass sie dort sind? Es ist besser, ein System zu erstellen, das Referenz von bekannten Objekten erlaubt.

1
B H

Suchen Sie rekursiv nach allen Steuerelementen, die dem angegebenen Prädikat entsprechen (ohne Root-Steuerelement):

    public static IEnumerable<Control> FindControlsRecursive(this Control control, Func<Control, bool> predicate)
    {
        var results = new List<Control>();

        foreach (Control child in control.Controls)
        {
            if (predicate(child))
            {
                results.Add(child);
            }
            results.AddRange(child.FindControlsRecursive(predicate));
        }

        return results;
    }

Verwendung:

myControl.FindControlsRecursive(c => c.ID == "findThisID");
1
DavidWainwright

Aktionsverwaltung für Steuerelemente

Erstellen Sie unter Klasse in Basisklasse. Klasse So erhalten Sie alle Steuerelemente:

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;
    }
}

Aus Datenbank: Alle Aktionen abrufen IDs (wie divAction1, divAction2 ....), die in DATASET (DTActions) dynamisch sind, lassen einen bestimmten Benutzer zu.

In Aspx: Geben Sie in HTML die Aktion (Schaltfläche, Anker usw.) in div oder span ein und geben Sie ihnen die ID like

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

IN CS: Verwenden Sie diese Funktion auf Ihrer Seite:

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;
                }

            }
        }
    }
1
atif

Das folgende Beispiel definiert einen Button1_Click-Ereignishandler. Beim Aufrufen verwendet dieser Handler die FindControl-Methode, um ein Steuerelement mit einer ID-Eigenschaft von TextBox2 auf der übergeordneten Seite zu suchen. Wenn das Steuerelement gefunden wird, wird sein übergeordnetes Steuerelement mithilfe der Parent-Eigenschaft bestimmt und die ID des übergeordneten Steuerelements wird auf die Seite geschrieben. Wenn TextBox2 nicht gefunden wird, wird "Steuerelement nicht gefunden" auf die Seite geschrieben.

private void Button1_Click(object sender, EventArgs MyEventArgs)
{
      // Find control on page.
      Control myControl1 = FindControl("TextBox2");
      if(myControl1!=null)
      {
         // Get control's parent.
         Control myControl2 = myControl1.Parent;
         Response.Write("Parent of the text box is : " + myControl2.ID);
      }
      else
      {
         Response.Write("Control not found");
      }
}
0
Sudhakar Rao