2014-11-03 2 views
0

Я хотел бы добавить usercontrols в PlaceHolder на моей странице динамически во время выполнения, на основе которого выбран DropDownList, выбранный пользователем. Что-то вроде этого:динамические пользовательские элементы управления и viewstate - что мне не хватает

protected void Page_Init(object sender, EventArgs e) 
{ 
    //get user's content selection 
    int contentMode; 

    if (!IsPostBack) 
     contentMode = 1; 
    else 
     contentMode = Int32.Parse(Request.Form[ddlMode.UniqueID]); 

    //load a user control 
    ContentControl ucContent = null; 

    switch (contentMode) 
    { 
     case 1: 
      ucContent = LoadControl("~/Controls/SomeContent1.ascx") as ContentControl; 
      break; 
     case 2: 
      ucContent = LoadControl("~/Controls/SomeContent2.ascx") as ContentControl; 
      break; 
    } 

    ucContent.ID = "ucContent"; 

    phContentArea.Controls.Add(ucContent); 
} 

... это почти работает, но после двух постбэков я получаю это:

Не удалось загрузить ViewState. Дерево управления, в которое загружается viewstate, должно соответствовать дереву управления, который использовался для сохранения состояния представления во время предыдущего запроса. Например, при добавлении элементов управления динамически элементы управления, добавленные во время обратной связи, должны соответствовать типу и положению элементов управления, добавленных во время первоначального запроса.

... который я прочитал из-за того, что элементы управления были разными во второй обратной передаче, чем предыдущая обратная передача. Я пытался предотвратить это, предоставив элементу управления тот же идентификатор и тип, но не кубики. Два элемента управления:

public partial class SomeContent1 : Foo.Bases.ContentControl 
{ 
    //code 
} 

public partial class SomeContent2 : Foo.Bases.ContentControl 
{ 
    //code 
} 

Есть ли часть головоломки, которую я пропускаю, чтобы сделать эту работу? Я читал подобные вопросы, но предложения не были плодотворными.

благодаря

ответ

0

В случае инициализации, вы должны убедиться, что дерево управления соответствует предыдущему дереву управления отправило обратно; поэтому, если вы удаляете элементы управления, вам нужно удалить его после запуска init, т.е. когда загружается viewstate.

Кроме того, в PreInit может потребоваться выполнить первоначальную загрузку, и вы можете попытаться выяснить, помогает ли это также.

+0

Я не могу явно удалять элементы управления, но, как и в Page_Init выше, я загружаю разные на основе выбранного значения списка. В приведенном выше коде загружается только UC для выбранного элемента, а остальные нет. Это, безусловно, приводит к несогласованному дереву управления viewstate. Но я не уверен, как решить - используя вышеприведенную модель, как я должен это сделать, чтобы предотвратить это? – mdelvecchio

+0

Да, это и является причиной проблемы. Вам придется перезагрузить предыдущее состояние, затем удалить старый элемент управления и добавить новый. С динамической точки зрения вы можете сохранить другую переменную ViewState, которая содержит текущее состояние, загрузить ее в init, а затем удалить старый и добавить новое, чтобы перейти в правильное состояние. Или просто загрузите все, как вы упомянули. –

0

другой метод, который работает, но отличается от того, в моем вопросе, чтобы добавить все элементы управления содержимым во время выполнения, но установить видимость невыбранных них к ложному:

switch (contentMode) 
{ 
    case 1: 
     ucContent = LoadControl("~/Controls/SomeContent1.ascx") as ContentControl; 
     phContentArea.Controls.Add(ucContent); 

     ucContent = LoadControl("~/Controls/SomeContent2.ascx") as ContentControl; 
     ucContent.Visible = false; 
     ucContent.EnableViewState = false; 
     phContentArea.Controls.Add(ucContent);  
     break; 

    case 2: 
     ucContent = LoadControl("~/Controls/SomeContent1.ascx") as ContentControl; 
     ucContent.Visible = false; 
     ucContent.EnableViewState = false; 
     phContentArea.Controls.Add(ucContent); 

     ucContent = LoadControl("~/Controls/SomeContent2.ascx") as ContentControl; 
     phContentArea.Controls.Add(ucContent); 
     break; 
} 

... но это не так хорошо, как загрузка только желаемого элемента управления.

+0

Я бы рекомендовал это, потому что управление динамическим управлением - это боль в веб-формах; однако у вас будет большая полезная нагрузка в представлении из-за количества элементов управления на странице. –

+0

Visible = False также не делает ничего для разметки, поэтому размер страницы тот же, но ViewState будет сохранен. –

+0

Вы всегда можете отключить ViewState в экземпляре usercontrol или любых дочерних элементах управления, если они не нужны. – sh1rts

Смежные вопросы