it-swarm.it

Ottieni tutti i controlli Web di un tipo specifico su una pagina

Ho riflettuto su come ottenere tutti i controlli su una pagina e quindi eseguire un compito su di essi in questa domanda correlata:

Come cercare attraverso un C # DropDownList a livello di codice

Ho bisogno di codice che possa scansionare la pagina, ottenere tutti i controlli DropDownList e restituirli in un elenco.

Al momento sto modificando ogni singolo controllo, preferirei essere in grado di eseguire il loop dinamico su ciascun controllo per preformare il mio compito.

31
Anicho

Controlla la mia precedente SO risposta .

Fondamentalmente, l'idea è di avvolgere la ricorsione di iterare attraverso la raccolta di controlli usando:

private void GetControlList<T>(ControlCollection controlCollection, List<T> resultCollection)
where T : Control
{
    foreach (Control control in controlCollection)
    {
        //if (control.GetType() == typeof(T))
        if (control is T) // This is cleaner
            resultCollection.Add((T)control);

        if (control.HasControls())
            GetControlList(control.Controls, resultCollection);
    }
}

e usarlo:

List<DropDownList> allControls = new List<DropDownList>();
GetControlList<DropDownList>(Page.Controls, allControls )
foreach (var childControl in allControls )
{
//     call for all controls of the page
}

[Modificato il 26/11/2013]: ecco un modo più elegante per raggiungere questo obiettivo. Ho scritto due metodi di estensione che possono guidare l'albero di controllo in entrambe le direzioni. I metodi sono scritti in un modo più lineare in quanto produce un enumerabile:

/// <summary>
/// Provide utilities methods related to <see cref="Control"/> objects
/// </summary>
public static class ControlUtilities
{
    /// <summary>
    /// Find the first ancestor of the selected control in the control tree
    /// </summary>
    /// <typeparam name="TControl">Type of the ancestor to look for</typeparam>
    /// <param name="control">The control to look for its ancestors</param>
    /// <returns>The first ancestor of the specified type, or null if no ancestor is found.</returns>
    public static TControl FindAncestor<TControl>(this Control control) where TControl : Control
    {
        if (control == null) throw new ArgumentNullException("control");

        Control parent = control;
        do
        {
            parent = parent.Parent;
            var candidate = parent as TControl;
            if (candidate != null)
            {
                return candidate;
            }
        } while (parent != null);
        return null;
    }

    /// <summary>
    /// Finds all descendants of a certain type of the specified control.
    /// </summary>
    /// <typeparam name="TControl">The type of descendant controls to look for.</typeparam>
    /// <param name="parent">The parent control where to look into.</param>
    /// <returns>All corresponding descendants</returns>
    public static IEnumerable<TControl> FindDescendants<TControl>(this Control parent) where TControl : Control
    {
        if (parent == null) throw new ArgumentNullException("control");

        if (parent.HasControls())
        {
            foreach (Control childControl in parent.Controls)
            {
                var candidate = childControl as TControl;
                if (candidate != null) yield return candidate;

                foreach (var nextLevel in FindDescendants<TControl>(childControl))
                {
                    yield return nextLevel;
                }
            }
        }
    }
}

Grazie alla parola chiave this, questi metodi sono metodi di estensioni e possono semplificare il codice.

Ad esempio, per trovare tutti DropDownList nella pagina, puoi semplicemente chiamare:

var allDropDowns = this.Page.FindControl<DropDownList>();

A causa dell'uso della parola chiave yield e poiché Linq è abbastanza intelligente da rinviare l'esecuzione dell'enumerazione, è possibile chiamare (ad esempio):

var allDropDowns = this.Page.FindDescendants<DropDownList>();
var firstDropDownWithCustomClass = allDropDowns.First(
    ddl=>ddl.CssClass == "customclass"
    );

L'enumerazione si interromperà non appena viene soddisfatto il predicato nel metodo First. L'intero albero di controllo non sarà percorribile.

57
Steve B
foreach (DropDownList dr in this.Page.Form.Controls.OfType<DropDownList>())
{

}
15
marko

Ho fatto proprio questa domanda e mentre ho trovato utile la risposta di Steve B, volevo un metodo di estensione, quindi lo ho rielaborato:

    public static IEnumerable<T> GetControlList<T>(this ControlCollection controlCollection) where T : Control
    {
        foreach (Control control in controlCollection)
        {
            if (control is T)
            {
                yield return (T)control;
            }

            if (control.HasControls())
            {
                foreach (T childControl in control.Controls.GetControlList<T>())
                {
                    yield return childControl;
                }
            }
        }
    }
5
bicbmx

Ecco una versione ricorsiva che restituisce una raccolta di controllo del tipo richiesto invece di utilizzare un altro argomento:

using System.Collections.Generic;
using System.Web.UI;
// ...
public static List<T> GetControls<T>(ControlCollection Controls)
where T : Control {
  List<T> results = new List<T>();
  foreach (Control c in Controls) {
    if (c is T) results.Add((T)c);
    if (c.HasControls()) results.AddRange(GetControls<T>(c.Controls));
  }
  return results;
}

Inserisci nella tua classe (statico opzionale).

5
Greg Searle

Puoi utilizzare la logica ricorsiva per ottenere tutti i controlli, in questo modo:

private void PopulateSelectList(Control parentCtrl, List<DropDownList> selectList)
{
    foreach (Control ctrl in parentCtrl.Controls)
    {
        if (ctrl is DropDownList)
        {
            selectList.Add(((DropDownList)ctrl);
            continue;
        }
        FindAllControls(ctrl, selectList);
    }
}
1
James Johnson

Effettuare il looping dei controlli su una pagina non è difficile: devi solo guardare all'interno di ogni controllo per avere più controlli.

Potresti fare qualcosa del genere

foreach(var control in Page)
{
    if(control is DropDownList)
    {
        //Do whatever
    }
    else
    {
        //Call this function again to search for controls within this control
    }
}
1
Mark Williams

Questo funziona se si utilizzano i componenti del modulo da system.web.ui Tuttavia questo non funziona quando li si utilizza da system.web.mvc in modo apparente così ho trovato il seguente lavoro.

for (Int32 idx = 0; idx < formCollection.Count; idx += 1)
                    {
                    String Name = formCollection.Keys[idx];
                    String value = formCollection[idx];

                    if (Name.Substring(0, 3).ToLower() == "chk")

                        {
                        Response.Write(Name + " is a checkbox <br/>");
                        }
                    else if (Name.Substring(0, 5).ToLower() == "txtar")
                        {
                        Response.Write(Name + " is a text area <br/>");
                        }
                    else if (Name.Substring(0, 2).ToLower() == "rd")
                        {
                        Response.Write(Name + " is a RadioButton <br/>");
                        }

                    }

Questo funziona per me però ho scoperto che il pulsante di opzione se non selezionato è null, quindi non restituisce nulla che sia ok non devo scrivere nulla nel database se è nullo 

0
        var dropDownLists = new List<DropDownList>();
        foreach (var control in this.Controls)
        {
            if (control is DropDownList)
            {
                dropDownLists.Add( (DropDownList)control );
            }
        }
0
dudeNumber4