views:

180

answers:

2

I have this weird problem when putting textboxes on the page in reverse. The whole event system is messed up. Changing one textbox fires TextChange on all textboxes. I can fix this by putting the controls in a list first and then call add while iterating trough the list in reverse. But i just want to know why this fails. Heres some code (.net 2.0)

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        InitFields();
    }

    private void InitFields()
    {
        int nrFields;
        //We have a static textbox called nrElements, this determines the number
        //of fields to initialize
        if (int.TryParse(nrElements.Text, out nrFields))
        {
            //Put all the dynamic fields on the screen in reverse order
            foreach(Control t in GetDynamicFields(nrFields))
            {
                //Calling Controls.Add works fine
                //Calling Controls.AddAt messes up the events
                //Try changing different textboxes
                plhFields.Controls.AddAt(0, t);
            }
        }
    }

    private IEnumerable<Control> GetDynamicFields(int nrFields)
    {
        for (int i = 0; i < nrFields; i++)
        {
            TextBox txtBox = new TextBox();
            txtBox.ID = string.Format("dynTextBox{0}", i.ToString());
            txtBox.AutoPostBack = true;
            txtBox.TextChanged += t_TextChanged;
            yield return txtBox;
        }
    }

    private void t_TextChanged(object sender, EventArgs e)
    {
        TextBox txtBox = sender as TextBox;
        if (txtBox != null)
            txtBox.Text = txtBox.Text + "Changed ";
    }
}
A: 

Try calling InitFields() on the Page_PreInit event rather than Page_Load.

Or an alternative would be to override the CreateChildControls() method (MSDN Article), if you use CreateChildControls() you'll need to call EnsureChildControls() on the Page_Load method to make sure the CreateChildControls() method has been called before you try to access any controls which have been created within that method.

Robert W
Wich controls I load depend on the input of the user in another textbox. The value of the textbox (userinput) is not loaded when PreInit runs. The same is true for CreateChildControls.
Then are the control IDs the same between every postback?
Robert W
A: 

Always put dynamic controls in OnInit event. Then viewstate serializer/deserializer will work. And you have to add controls on every request, not just in !IsPostBack.

Hrvoje
How do I access controls from the OnInit event? calling txtUserInput.Text doesn't work
Well, all input elements on form are not deserialised in OnInit event, so I use Request.Form["ctl00_txtInput"] for reading text boxes. But "ctl00_....._txtInput" is not recommented because prefix "ctl00_..." can change, accourding to position of you text box. You can use it just for testing, and you can find the name by looking at HTML of you rendered page. Also, I recomment building helper method, that iterates through key-value pairs inside Request.Form, and search for "txtUserInput" inside key, and returns its value! I can post code, if you wish.
Hrvoje