Domanda

Se volessi trovare le caselle di controllo selezionate su una pagina ASP.NET potrei usare la seguente query LINQ.

var checkBoxes = this.Controls
                     .OfType<CheckBox>()
                     .TakeWhile<CheckBox>(cb => cb.Checked);

Funziona bene se le caselle di controllo sono nidificate nella raccolta di controlli corrente, ma mi piacerebbe sapere come estendere la ricerca eseguendo il drill-down nelle raccolte di controlli dei controlli di livello superiore.

La domanda è stata posta qui:

Ricerca di controlli che utilizzano una determinata interfaccia in ASP.NET

E ho ricevuto risposte non LINQ, ho già la mia versione di una ricerca di controllo ricorsivo su tipo e ID come metodi di estensione, ma mi chiedevo solo quanto sia facile farlo in LINQ?

È stato utile?

Soluzione

Prendi il tipo / ID controllando la ricorsione, quindi basta avere un " dammi tutti i controlli, ricorsivamente " metodo, ad esempio

public static IEnumerable<Control> GetAllControls(this Control parent)
{
    foreach (Control control in parent.Controls)
    {
        yield return control;
        foreach(Control descendant in control.GetAllControls())
        {
            yield return descendant;
        }
    }
}

È un po 'inefficiente (in termini di creazione di molti iteratori) ma dubito che avrai un albero molto profondo .

È quindi possibile scrivere la query originale come:

var checkBoxes = this.GetAllControls()
                     .OfType<CheckBox>()
                     .TakeWhile<CheckBox>(cb => cb.Checked);

(EDIT: ha cambiato AllControls in GetAllControls e lo usa correttamente come metodo.)

Altri suggerimenti

public static IEnumerable<Control> AllControls(this Control container)
{
    //Get all controls
    var controls = container.Controls.Cast<Control>();

    //Get all children
    var children = controls.Select(c => c.AllControls());

    //combine controls and children
    var firstGen = controls.Concat(children.SelectMany(b => b));

    return firstGen;
}

Ora in base alla funzione sopra, possiamo fare qualcosa del genere:

public static Control FindControl(this Control container, string Id)
{
    var child = container.AllControls().FirstOrDefault(c => c.ID == Id);
    return child;
}

Il mio suggerimento per rendere ricorsivo il AllControls è:

    public static IEnumerable<Control> AllControls(this Control parent)
    {
        foreach (Control control in parent.Controls)
        {
             yield return control;
        }
        foreach (Control control in parent.Controls)
        {
            foreach (Control cc in AllControls(control)) yield return cc;
        }
    }

Il secondo foreach sembra strano, ma questo è l'unico modo che conosco per "appiattire" la chiamata ricorsiva.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top