Cannot get values in OnInit event

2019-08-01 07:55发布

问题:

I understand the order the events occur with page life cycle but it is not helping with my situation. I have a checkboxlist that is populated by a directory filled with forms. When I check a box next to the name of the form I would like it to dynamically create a wizard step and insert the form.

Order of events: OnInit: GatherForms() - Checks directory and loads all form names into checkbox LoadForms() - Checks "Selected" Session and loads forms that were collected

CheckBoxList:SelectedIndexChanged #AutoPost = true# PopulateForms() - Loops through the checkboxs and adds them to session state

When the user clicks the checkbox it does a postback and hits the OnInit which pulls from the session. The problem is that PopulateForms() was not ran yet so it populated nothing even though it is checked. If I click another item it will postback and appear. I cannot seem to be able to pull any kind of useful information from the checkbox before the refresh which means I cannot see the forms appear immediately. I have also tried looping the checkbox but unfortunately viewstate hasnt posted yet. sigh.

Any suggestions?

Thanks!

P.S: I cannot use Request.Form[] because I have to get all the selected items out of the checkbox. maybe i can but i cannot find a way :/

回答1:

This is a common problem I wrestle with as I get better at ASP.NET.

With dynamic controls you have the problem of them not actually existing during OnInit.

What you can do is create all of the controls the user may see during OnInit, and hide the elements the user won't see in code. The page will load, all possible controls will be instantiated (in code - don't worry this appearing in your HTML and bloating it), then the event handler will fire, and then you can deal with setting the visibility of your wizard.

For example:

public void OnInit(object sender, EventArgs e)
{
    GatherForms();
    CreateWizardForm(); // creates a wizard and adds controls it will need
}

private void Checkbox_Checked(object sender, EventArgs e)
{
    var checkBox = (CheckBox)sender;
    // append checkBox.SelectedValue to session state object of checkboxes
}

protected override void OnPreRender(object sender, EventArgs e)
{
    if (/* Session checkboxes contain values */)
    {
        this.WizardForm.Visible = true;
        this.CheckboxList.Visible = false;
    }
}

This works provided you know ahead of time which controls will be in the wizard form. You can change the values of those controls in the OnPreRender event, toggle their visibility, etc, but you can't go and add new controls (e.g. Controls.Add(new Button())) - that has to be done in the OnInit event.



回答2:

Only add your dynamic controls in OnInit. Don't do any population/processing until PageLoad. You will retain your values this way.



回答3:

A classic pitfall with dynamic controls.

Honestly the best solution is to just wield the Request values array to look for the information you need and ignore the lifecycle stuff for this particular situation.

In OnInit(), the posted values are there, they just haven't been dealt with by ViewState yet. So you can just do if (Request["myCheckBoxName"] == xxx) to deal with individual checkboxes, or if you can use Request["__EVENTTARGET"] to get the name of the control that caused the postback.

See my old answer here for a more thorough discussion of the issue.