Iterating through textbox controls in a panel C#

2019-06-11 08:11发布

问题:

I have seen many others with similar problems but I cannot find the flaw in my logic here. Any help would be greatly appreciated.

I have a Panel which I have added numerous label and textbox controls to, ie:

myPanel.Controls.Add(txtBox);

These controls are created and added in a method called previous to the iteration method.

I want to iterate through each textbox and use its Text property as a parameter in another method but I am not having any luck. Here is my attempt to iterate:

public void updateQuestions()
{
    try
    {
        foreach (Control c in editQuestionsPanel.Controls)
        {
            if (c is TextBox)
            {
                TextBox questionTextBox = (TextBox)c;

                string question = questionTextBox.Text;

                writeNewQuestionToTblQuestions(question);
            }
        }
    }
    catch (Exception err)
    {
        Console.WriteLine(err.Message);
    }
}

The problem I am having is that the controls are not in the Panel when I arrive at this updateQuestions() method. Here is the process involved:

A commandButton is clicked and the questions are read from a DB, for each question a method is called which adds 2 labels and a textbox to editQuestionsPanel.Controls. This panel is inside a PlaceHolder which is then made visible.

When a button inside the PlaceHolder is clicked, the updateQuestions() method is called and the editQuestionsPanel.Controls.Count = 1. As there are approx 12 questions in the DB it should be around 36. The one control inside the Panel is of type:

System.Web.UI.LiteralControl  

It contains no controls.

I am sure that somwhere in the lifecycle the Panel's controls are being cleared but I do not know how to step thru the life cycle. I have a Page_load method which is called as soon as a button is clicked but once the button which calls updateQuestions() is clicked the editQuestionsPanel.Controls.Count is already back to 1 so it must be cleared before this but I do not know how to correct this...

Any help you can give to help me solve this would be greatly appreciated - its killing me!

回答1:

When you add controls dynamically, you need to do that on every request - asp.net doesn't do that for you!

Add the controls in the Init or Load phase, then they will get populated with the postback values.



回答2:

This selects from collection controls only that which are of type TextBox.

(the same as control is TextBox or (control as TextBox) != null)

If controls are contained in editQuestionsPanel.Controls:

using System.Linq;

IEnumerable<TextBox> textBoxes = editQuestionsPanel.Controls.OfType<TextBox>();    
foreach (TextBox textBox in textBoxes)
{
    // do stuff
}

To select all child controls use next extension method:

public static IEnumerable<T> GetChildControls<T>(this Control control) where T : Control
{
    var children = control.Controls.OfType<T>();
    return children.SelectMany(c => GetChildControls<T>(c)).Concat(children);
}

Using:

IEnumerable<TextBox> textBoxes = editQuestionsPanel.GetChildControls<TextBox>();


回答3:

A frequently made mistake: Container.Controls only contains the first level child controls in this container. That is: TextBox1 in PanelA, PanelA in PanelB, you can't get TextBox1 in PanelB.Controls.

My solution is to write an extension method:

public static IEnumerable<Control> AllControls(this Control ctl)
{
   List<Control> collection = new List<Control>();
   if (ctl.HasControls())
   {
       foreach (Control c in ctl.Controls)
       {
             collection.Add(c);
             collection = collection.Concat(c.AllControls()).ToList();
       }
   }
   return collection;
}

Now TextBox1 is in PanelB.AllControls(). To filter all controls with type, using PanelB.AllControls().OfType<TextBox>()



回答4:

If the other answers don't help, try doing your code but add recursivity. Your code would not work if it's editQuestionsPanel => Panel => Textbox



回答5:

You can do something like this instead:

var questions = from tb in editQuestionsPanel.Controls.OfType<TextBox>()
                select tb.Text;

foreach(var question in questions)
{
    writeNewQuestionToTblQuestions(question);
}


回答6:

Try this

        int Count = 0;
        foreach (Control ctr in Panel1.Controls)
        {
            if (ctr is TextBox)
                Count++;
        }