web-dev-qa-db-fra.com

Boucle dans les zones de texte

J'ai une application Winforms qui a 37 zones de texte à l'écran. Chacun est numéroté séquentiellement:

DateTextBox0
DateTextBox1 ...
DateTextBox37

J'essaie de parcourir les zones de texte et d'attribuer une valeur à chacune d'entre elles:

int month = MonthYearPicker.Value.Month;
int year = MonthYearPicker.Value.Year;
int numberOfDays = DateTime.DaysInMonth(year, month);

m_MonthStartDate = new DateTime(year, month, 1);
m_MonthEndDate = new DateTime(year, month, numberOfDays);

DayOfWeek monthStartDayOfWeek = m_MonthStartDate.DayOfWeek;
int daysOffset = Math.Abs(DayOfWeek.Sunday - monthStartDayOfWeek);

for (int i = 0; i <= (numberOfDays - 1); i++)
{
 //Here is where I want to loop through the textboxes and assign values based on the 'i' value
   DateTextBox(daysOffset + i) = m_MonthStartDate.AddDays(i).Day.ToString();
}

Permettez-moi de préciser que ces zones de texte apparaissent sur des panneaux distincts (37 d'entre eux). Donc, pour pouvoir utiliser une foreach en boucle, je dois parcourir les contrôles principaux (les panneaux), puis les contrôles des panneaux. Ça commence à se compliquer.

Des suggestions sur la façon dont je peux affecter cette valeur à la zone de texte?

15
Taryn

Pour obtenir tous les contrôles et sous-contrôles de manière récursive du type spécifié, utilisez cette méthode d'extension:

public static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
{
    var children = (control.Controls != null) ? control.Controls.OfType<TControl>() : Enumerable.Empty<TControl>();
    return children.SelectMany(c => GetChildControls<TControl>(c)).Concat(children);
}

usage:

var allTextBoxes = this.GetChildControls<TextBox>();
foreach (TextBox tb in allTextBoxes)
{
    tb.Text = ...;
}
37
abatishchev

Vous pourriez boucler toutes les commandes du formulaire en demandant une à une s'il s'agit d'une "zone de texte" et en renvoyer la liste complète. 

public List GetTextBoxes(){   
    var textBoxes = new List();   
        foreach (Control c in Controls){   
            if(c is TextBox){   
                textBoxes.add(c);   
        }   
    }   
return textBoxes;   
}
6
JAiro

Vous pouvez parcourir les zones de texte de votre formulaire d’une manière assez simple:

Func<ControlCollection, List<TextBox>> SearchTextBoxes = null;
SearchTextBoxes = coll => {
    List<TextBox> textBoxes = new List<TextBox>();

    foreach (Control c in coll) {
        TextBox box = c as TextBox;
        if (box != null)
           textBoxes.Add(box);
        if (c.Controls.Count > 0)
           textBoxes.AddRange(SearchTextBoxes(c.Controls));
    }

    return textBoxes;
};

var tbs = SearchTextBoxes(this.Controls).OrderBy(tb => tb.Name);

Modifier: modifié en fonction des nouvelles exigences. Pas aussi élégant que la solution LINQ, bien sûr :)

4
Christian

Puisque ce message semble se ressusciter de temps en temps et que les solutions ci-dessus ne trouvent pas de contrôles à l'intérieur de contrôles, comme dans une zone de groupe, ils les trouveront. Ajoutez simplement votre type de contrôle:

    public static IList<T> GetAllControls<T>(Control control) where T : Control
    {
        var lst = new List<T>();
        foreach (Control item in control.Controls)
        {
            var ctr = item as T;
            if (ctr != null)
                lst.Add(ctr);
            else
                lst.AddRange(GetAllControls<T>(item));

        }
        return lst;
    }

Et c'est usage:

        var listBoxes = GetAllControls<ListBox>(this);
        foreach (ListBox lst in listBoxes)
        {
            //Do Something
        }
2
Zath .

Parcourez les contrôles du formulaire et vérifiez le nom du contrôle s'il correspond, puis définissez la propriété Text comme vous le souhaitez.

int i = 0;
foreach (Control contrl in this.Controls) {
    if (contrl.Name == ("DateTextBox" + i.ToString())) {
        contrl.Text = "requiredtexttobeset";
    }
    i = i + 1;
}
2
Ismail

Si vous voulez vous passer de 'foreach' (si vous avez des cases spécifiques à ajuster/adresse)

int numControls = Page.Form.Controls.Count;

    for (int i = 0; i < numControls; i++)
    {
        if (Page.Form.Controls[i] is TextBox)
        {
            TextBox currBox = Page.Form.Controls[i] as TextBox;
            currbox.Text = currbox.TabIndex.ToString();
        }
    }
1
Mark

Vous pouvez simplement faire ce compagnon ...

foreach (TextBox txt in this.Panel.Controls.OfType<TextBox>())
            {
                txt.Text="some value you assign";
            }

Si vos zones de texte se trouvent directement sur le formulaire et non sur un panneau, vous pouvez remplacer this.Panel.Controls par this.Controls. Cela devrait être assez court et clair pour vous.

1
indago
        //THE EASY WAY! Always post easy solutions. It's the best way.
        //This code is used to loop through all textboxes on a form for data validation. 
        //If an empty textbox is found, Set the error provider for the appropriate textbox.
        foreach (var control in Controls)
        {
            if (control is TextBox)
            {
                //Box the control into a textbox. Not really needed, but do it anyway
                var textbox = (TextBox)control;

                if (String.IsNullOrWhiteSpace(textbox.Text))
                {
                    //Set the errorProvider for data validation
                    errorProvider1.SetError(textbox, "Data Required!");
                    textbox.Text = String.Empty; //Clear out the whitespace if necessary
                    //blnError = true;
                }
            }
        }
1
puffgroovy

Après l'appel InitialiseComponents(), ajoutez les zones de texte à une variable de membre de collection du formulaire. Vous pouvez ensuite les parcourir dans l'ordre plus tard.

0
Neil Barnwell

Puisque vous connaissez déjà le nom du contrôle, vous pouvez donc rechercher le contrôle par son nom.

Voir Obtenir un contrôle Windows Forms par son nom en C #

0
Ramesh Soni

D’autres réponses ne vous suffisent pas?
J'ai trouvé cela comme une réponse à une question similaire sur SO, mais je ne trouve pas le fil maintenant. Il parcourt de manière récursive TOUS les contrôles d'une type donnée situés dans une control. Cela inclut donc les enfants d’enfants d’enfants de ... etc. Mon exemple change la ForeColor de chaque TextBox en Hot Pink!

public IEnumerable<Control> GetAllControlsOfType(Control control, Type type)
{
    var controls = control.Controls.Cast<Control>();

    return controls.SelectMany(ctrl => GetAllControlsOfType(ctrl, type))
                              .Concat(controls)
                              .Where(c => c.GetType() == type);
}

La mise en oeuvre: 

IEnumerable<Control> allTxtBxs = GetAllControlsOfType(this, typeof(TextBox));
foreach (TextBox txtBx in allTxtBxs)
{
    txtBx.ForeColor = Color.HotPink;
}

Assez similaire à la réponse de abatishchev (qui, pour moi , ne retourne que de premier niveau contrôles enfants), mais suffisamment différente pour mériter sa propre réponse, je pense.

0
n00dles

Vous pouvez créer une Dictionary de TextBox, int comme suit

Dictionary<TextBox, int> textBoxes = new Dictionary<TextBox, int>();

foreach (TextBox control in Controls.OfType<TextBox>())
    textBoxes[control] = Convert.ToInt32(control.Name.Substring(11));

Maintenant .. pour les parcourir en boucle ..

foreach (var item in textBoxes.Select(p => new { textBox = p.Key, no = p.Value}))
     item.textBox.Text = item.no.ToString(); // whatever you want...

Bonne chance!

0
Homam