Re: Dynamically Loading a UserControl

From: Jeff Evans (jwevans1_at_you_eye_you_see.edu)
Date: 12/18/04


Date: Sat, 18 Dec 2004 12:29:55 -0600

Harry < robinsoh@vu.union.edu > wrote:
> Hello Again,
> Quick update, I have added code to my Page_Load event such that it will
> only load the control named in the ViewState if the PostBack was NOT
> raised by the RadioButtonList. The updated code looks as follows:
> if (ViewState["ControlName"] != null &&
> Request["__EVENTTARGET"] != ModeRadioButtonList.ClientID + "_0" &&
> Request["__EVENTTARGET"] != ModeRadioButtonList.ClientID + "_1" &&
> Request["__EVENTTARGET"] != ModeRadioButtonList.ClientID + "_2")
> This corrects the problem, however, an exception is thrown when switching
> user controls to load by clicking various radio buttons in the list. The
> exception reads as follows:
> Failed to load viewstate. The control tree into which viewstate is being
> loaded must match the control tree that was used to save viewstate during
> the previous request. For example, when adding controls dynamically, the
> controls added during a post-back must match the type and position of the
> controls added during the initial request.
> Looks like my updated solution is not acceptable afterall. This is puzling
> since the ASP.NET exception indicates the control must be reloaded during
> the PostBack, however, I did this the first time around and then removed
> it when the SelectedIndexChanged event occured and replaced it with the
> requested UserControl, but that solution failed as well since the newly
> added UserConrol did not handle PostBacks correctly (see my original
> code). - Harry
> "Harry" <robinsoh@vu.union.edu> wrote in message
> news:%23fH5CAG5EHA.3644@tk2msftngp13.phx.gbl...
>> Hello,
>> I have a page with a RadioButtonList and a PlaceHolder control. The
>> RadioButtonList's AutoPostBack attribute is set to TRUE and its
>> SelectedIndexChanged event loads one of three UserControls into the
>> PlaceHolder's child control collection depending upon which of the three
>> radio buttons is selected. Each of the three UserControls have postback
>> events themselves triggered by button clicks. The problem I'm having is
>> keeping track of what UserControl to load upon a page being posted back.
> My
>> SelectedIndexChanged event will load a UserControl dynamically just fine,
>> however, in the event that the dynamically loaded user control itself
> issues
>> a postback the parnets Page_Load event must remeber which UserControl to
>> reload so it can handle its postback. In order to do this, I store the
>> loaded control's name in the ViewState. This solution causes a problem in
>> that moveing from one dynamically loaded UserControl to another will
>> cause two controls to be displayed at the same time. To fix this my
>> SelectedIndexChanged event will remove the first child control in the
>> PlaceHolder. However, this solution totally screws with my postback such
>> that they do not fire porperly. Here is an example of what I'm doing:
>> private void Page_Load(object sender, System.EventArgs e)
>> {
>> if (ViewState["ControlName"] != null)
> PlaceHolderControl.Controls.Add(LoadControl(ViewState["ControlName"].ToStr
> in
>> g()));
>> }
>> private void MyRadioButtonList_SelectedIndexChanged(object sender,
>> System.EventArgs e)
>> {
>> if (PlaceHolderControl.HasControls())
>> PlaceHolderControl.Controls.RemoveAt(0);
>> ViewState["ControlName"] = MyRadioButtonList.SelectedValue;
> PlaceHolderControl.Controls.Add(LoadControl(MyRadioButtonList.SelectedValu
> e)
>> );

I have the least hassle with dynamic controls when I have references to each
possible Control explicity, then just create a new object for that reference
and add it to the placeholder as needed. For instance:

Control uc1;
Control uc2;

if (someCondition)
{
   uc1 = LoadControl("UserControl1");
   uc1.ID = "uc1";
   placeHolder.Controls.Add(uc1);
}
else
{
   //load uc2 in same manner
}

At any rate, if I had to guess I'd say the reason Viewstate is getting
confused has to do with naming conflicts. Unless you explicitly set the ID,
it will usually get something like "_ctl4" or something, where "4" is
however many auto-named controls there have been so far. What might be
happening then is:

1) On first request, you load a UserControl of type "UC1" to the
placeholder, ID is not explicitly set, so it is "_ctl1"
2) You make a postback
3) On this request, you want to switch to a different control, "UC2" so you
load it, it gets same ID "_ctl1" and ViewState goes to try to load - blows
up because it's a different control than "_ctl1" was before

In short, I would try either setting the ID explicity within each user
control you have to something unique or setting it when you create it in the
parent.


Loading