views:

305

answers:

1

Edit at bottom with solution

I've seen a similar question to this posted before and have tried the suggestions, but I must be missing something. My basic problem is this: I have a select box where the user can select a filter which may or may not have constraints built into it (requires the user to input further data so the filter knows how to filter). Since it's unknown just how many constraints will exist for the filter, I'm trying to load them in dynamically and add them to a placeholder panel that I have. The correct number of constraints load just fine and dandy, but when the user inputs text and hits submit, after the page reloads none of the values persist. Here's the appropriate code (I can provide more if needed):

I have these as class variables for my Web Part:

Panel constraintPanel;
HtmlInputText[] constraints;
Label[] constraintLabels = null;

Inside an override CreateChildControls I initialize the panel:

constraintPanel = new Panel();

I build in the dynamic input boxes in an overridden OnPreRender (Note: I've heard people say to do it in OnInit, OnLoad, or OnPreRender, but OnPreRender is the only one that doesn't make the whole Web Part error out):

protected override void OnPreRender(EventArgs e)
{
    buildConstraints();
    base.OnPreRender(e);
}

private void buildConstraints()
{
    if (!viewSelect.SelectedValue.Equals(INConstants.NoFilterOption))
    {
        string[,] constraintList = docManager.GetFilterConstraints(viewFilterSelect.SelectedValue);
        if (constraintList != null)
        {
            this.constraints = new HtmlInputText[constraintList.Length / 2];
            this.constraintLabels = new Label[constraintList.Length / 2];
            for (int constraintCount = 0; constraintCount < constraintList.Length / 2; constraintCount++)
            {
                Label constraintLabel = new Label();
                constraintPanel.Controls.Add(constraintLabel);
                constraintLabel.Text = constraintList[constraintCount, 0];
                this.constraintLabels[constraintCount] = constraintLabel;

                HtmlInputText constraint = new HtmlInputText();
                constraintPanel.Controls.Add(constraint);
                constraint.ID = "constraint_" + constraintCount;
                constraint.MaxLength = 12;
                constraint.Style.Add("FONT-FAMILY", "Verdana");
                constraint.Style.Add("FONT-SIZE", "11");
                this.constraints[constraintCount] = constraint;
            }
        }
    }
}

And then finally inside an overridden RenderWebParts I have (note: I've also tried looping through the arrays constraints and constraintLabels to render the controls, but it made no difference):

...
constraintPanel.RenderBeginTag(output); // not sure if this is needed
if (constraints != null && constraints.Length > 0)
{
    foreach (Control tempControl in constraintPanel.Controls)
    {
        if (tempControl is Label)
        {
            output.WriteLine("<tr>");
            output.WriteLine("<td width='2%' nowrap><font class='search-header'>");
            tempControl.RenderControl(output);
            output.WriteLine("&nbsp;");
        }
        else if (tempControl is HtmlInputText)
        {
            tempControl.RenderControl(output);
            output.WriteLine("</td>");
            output.WriteLine("<td width='*' nowrap></td>");
            output.WriteLine("</tr>");
        }
    }
}
constraintPanel.RenderEndTag(output); // not sure if this is needed
...

I appreciate any help, as this is truly driving me crazy.

Edit with solution:

I've been able to get it working. I needed to override the OnLoad event and wrap my calls from there in a try-catch block. For some reason the initial page load throws an exception when trying to run, which causes the entire page to not display. I also forgot to add my constraintPanel to the Controls list.

Here's the code in OnLoad for information's sake:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    try
    {
        viewsBuildConstraints();
    }
    catch (Exception)
    {
    }
}
+2  A: 

Try marking your webpart with the INamingContainer interface and make sure to give all controls an ID. Furthermore, HtmlInput COntrols do not have a viewstate i believe, which would cause them to "forget" the input after a postback. Could you try using actual TextBox controls?

Colin
I actually ended up giving unique ID's to the input boxes. I found out that they do save state, I was just building them at the wrong time. I've edited my question to reflect this.
Adam
Glad to see you found a workaround. It does look like a quickfix though.... I encourage you to dig deeper when you have the time...
Colin
I had a similar problem with TextBox controls not preserving their state. Simply adding the INamingContainer helped.
bryanbcook