neonbarbarian
neonbarbarian

Reputation: 55

Viewstate Problems loading dynamic Controls (with ListBox)

this is my frist question, I apologize if I do something wrong. Also I'm new to Asp.net. Here is my Problem:

I have an "Add Control Button" which adds a User Control with nothing more than a preconfigured ListBox. (The Idea is adding UserControls, as many, as the User needs.) So far so good. When I mark an element inside ListBox, Selection gets lost after 1st postback (for example after clicking add control button).Seems to be a Lifecycle Problem, dunno. My faulty Solution (adjusted from what I found on the net) is as follows: I use a List to restore every User Control based in its ID. Thank you. Here's the code:

protected List<string> ControlsList
{
    get
    {
        if (ViewState["controls"] == null)
        {
            ViewState["controls"] = new List<string>();
        }
        return (List<string>)ViewState["controls"];
    }
}

//Restore Controls based on IDs in ControlsList
protected override void LoadViewState(object savedState)
{
    base.LoadViewState(savedState);        

foreach (string contrID in ControlsList)
    { 
            Control c;
            c = LoadControl("v1.ascx");
            c.ID = "v1-" + contrID;
            PlaceHolder1.Controls.Add(c);
      }

//Button Click adds Control
protected void addControl(object sender, EventArgs e)
{
    Control c;
    c = LoadControl("v1.ascx");
    c.ID = "v1-" + NextID.ToString();
    ControlsList.Add(c.ID);
    PlaceHolder1.Controls.Add(c);
}

Here the User Control:

public partial class v1 : System.Web.UI.UserControl
{
protected void Page_Init(object sender, EventArgs e)
{
    v1_ListBox1.DataSourceID = "A1Vm1_SqlDataSource";
    v1_ListBox1.DataTextField = "Vm1";
    v1_ListBox1.DataValueField = "Vm1";
    v1_ListBox1.SelectionMode = ListSelectionMode.Multiple;

}

Upvotes: 0

Views: 786

Answers (1)

Knaģis
Knaģis

Reputation: 21485

You should change how your ViewState is saved

protected override object SaveViewState()
{
    var a = this.ControlsList;
    var b = base.SaveViewState();
    if (a.Count == 0 && b == null)
        return null;

    return new System.Web.UI.Pair(a, b);
}

protected override void LoadViewState(object savedState)
{
    if (savedState == null)
        return;

    var pair = (System.Web.UI.Pair)savedState;
    if (pair.First != null)
    {
        foreach (var id in (IList<string>)pair.First)
        {
            // add the control
        }
    }

    if (pair.Second != null)
        base.LoadViewState(pair.Second);
}

This approach will let you first initialize the child controls and then load the viewstate for them.

You might also want to add ViewStateModeByIdAttribute to this control that is adding the controls dynamically so that the loading of viewstate will not fail once you start removing the controls.

Upvotes: 1

Related Questions