0

У меня есть страница с LinkButton, которая при нажатии на нее я хотел бы добавить Usercontrol на страницу. Мне нужно иметь возможность добавлять/удалять столько элементов управления, сколько захочет пользователь. Usercontrol состоит из трех dropdownlists. Первый dropdownlist имеет свойство auotpostback, равное true, и подключает событие OnSelectedIndexChanged, которое при запуске будет загружать оставшиеся два dropdownlists с соответствующими значениями.Сохранение динамических пользовательских элементов управления ... Помощь!

Моя проблема заключается в том, что независимо от того, где я помещаю код на главную страницу, пользовательский контроль не загружается должным образом. Я знаю, что мне нужно воссоздать usercontrols при каждой обратной передаче, и я создал метод, который выполняется в методе OnPreInit для хостинга. Я все еще получаю следующую ошибку: Сбор управления не может быть изменен во время фаз DataBind, Init, Load, PreRender или Unload.

Это мой код: Спасибо !!!!

bool createAgain = false; 
    IList<FilterOptionsCollectionView> OptionControls 
    { 
     get 
     { 
      if (SessionManager.Current["controls"] != null) 
       return (IList<FilterOptionsCollectionView>)SessionManager.Current["controls"]; 
      else 
       SessionManager.Current["controls"] = new List<FilterOptionsCollectionView>(); 
      return (IList<FilterOptionsCollectionView>)SessionManager.Current["controls"]; 
     } 
     set 
     { 
      SessionManager.Current["controls"] = value; 
     } 
    } 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     Master.Page.Title = Title; 
     LoadViewControls(Master.MainContent, Master.SideBar, Master.ToolBarContainer); 
    } 

    protected override void OnPreInit(EventArgs e) 
    { 
     base.OnPreInit(e); 
     System.Web.UI.MasterPage m = Master; 
     Control control = GetPostBackControl(this); 
     if ((control != null && control.ClientID == 
         (lbAddAndCondtion.ClientID) || createAgain)) 
     { 
      createAgain = true; 
      CreateUserControl(control.ID); 
     } 
    } 

    protected void AddAndConditionClicked(object o, EventArgs e) 
    { 
     var control = LoadControl("~/Views/FilterOptionsCollectionView.ascx"); 
     OptionControls.Add((FilterOptionsCollectionView)control); 
     control.ID = "options" + OptionControls.Count.ToString(); 
     phConditions.Controls.Add(control); 
    } 



    public event EventHandler<Insight.Presenters.PageViewArg> OnLoadData; 



    private Control FindControlRecursive(Control root, string id) 
    { 
     if (root.ID == id) 
     { 
      return root; 
     } 
     foreach (Control c in root.Controls) 
     { 
      Control t = FindControlRecursive(c, id); 
      if (t != null) 
      { 
       return t; 
      } 
     } 
     return null; 
    } 

    protected Control GetPostBackControl(System.Web.UI.Page page) 
    { 
     Control control = null; 
     string ctrlname = Page.Request.Params["__EVENTTARGET"]; 
     if (ctrlname != null && ctrlname != String.Empty) 
     { 
      control = FindControlRecursive(page, ctrlname.Split('$')[2]); 
     } 
     else 
     { 
      string ctrlStr = String.Empty; 
      Control c = null; 
      foreach (string ctl in Page.Request.Form) 
      { 
       if (ctl.EndsWith(".x") || ctl.EndsWith(".y")) 
       { 
        ctrlStr = ctl.Substring(0, ctl.Length - 2); 
        c = page.FindControl(ctrlStr); 
       } 
       else 
       { 
        c = page.FindControl(ctl); 
       } 
       if (c is System.Web.UI.WebControls.CheckBox || 
       c is System.Web.UI.WebControls.CheckBoxList) 
       { 
        control = c; 
        break; 
       } 
      } 
     } 
     return control; 
    } 


    protected void CreateUserControl(string controlID) 
    { 
     try 
     { 
      if (createAgain && phConditions != null) 
      { 
       if (OptionControls.Count > 0) 
       { 
        phConditions.Controls.Clear(); 
        foreach (var c in OptionControls) 
        { 
         phConditions.Controls.Add(c); 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

Вот код в UserControl в:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="FilterOptionsCollectionView.ascx.cs" Inherits="Insight.Website.Views.FilterOptionsCollectionView" %> 


namespace Insight.Website.Views 

{ [ViewStateModeById] общественного частичного класса FilterOptionsCollectionView: System.Web.UI.UserControl { защищен недействительным Page_Load (объект отправителя, EventArgs е) {

} 

    protected override void OnInit(EventArgs e) 
    { 
     LoadColumns(); 
     ddlColumns.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(ColumnsSelectedIndexChanged); 
     base.OnInit(e); 
    } 

    protected void ColumnsSelectedIndexChanged(object o, EventArgs e) 
    { 
     LoadCriteria(); 
    } 

    public void LoadColumns() 
    { 
     ddlColumns.DataSource = User.GetItemSearchProperties(); 
     ddlColumns.DataTextField = "SearchColumn"; 
     ddlColumns.DataValueField = "CriteriaSearchControlType"; 
     ddlColumns.DataBind(); 
     LoadCriteria(); 
    } 

    private void LoadCriteria() 
    { 
     var controlType = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].CriteriaSearchControlType; 

     var ops = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].ValidOperators; 
     ddlOperators.DataSource = ops; 
     ddlOperators.DataTextField = "key"; 
     ddlOperators.DataValueField = "value"; 
     ddlOperators.DataBind(); 

     switch (controlType) 
     { 
      case ResourceStrings.ViewFilter_ControlTypes_DDL: 
       criteriaDDL.Visible = true; 
       criteriaText.Visible = false; 

       var crit = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].SearchCriteria; 
       ddlCriteria.DataSource = crit; 
       ddlCriteria.DataBind(); 
       break; 
      case ResourceStrings.ViewFilter_ControlTypes_Text: 
       criteriaDDL.Visible = false; 
       criteriaText.Visible = true; 
       break; 
     } 
    } 

    public event EventHandler OnColumnChanged; 
    public ISearchCriterion FilterOptionsValues { get; set; } 
} 

}

ответ

1

Я понял. Вот мое решение:

Я модифицировал GetPostBackControl, чтобы искать не только ссылку, которая вставляет пользовательский элемент управления, но и элементы управления, которые содержат идентификатор дочерних элементов вставляемого пользовательского элемента управления (как для захвата OnSelectedIndexChanged, который запускается изнутри моего пользовательского элемента управления).

protected Control GetPostBackControl(System.Web.UI.Page page) 
    { 
     Control control = null; 
     string ctrlname = Page.Request.Params["__EVENTTARGET"]; 
     if (ctrlname != null && ctrlname != String.Empty) 
     { 
      //if it contains options then it's a control inside my usercontrol 
      if (ctrlname.Split('$')[2].Contains("options")) 
      { 
       var c = new Control(); 
       c.ID = ctrlname; 
       return c; 
      } 
      else 
      { 
       control = FindControlRecursive(page, ctrlname.Split('$')[2]); 
      } 
     } 
     else 
     { 
      string ctrlStr = String.Empty; 
      Control c = null; 
      foreach (string ctl in Page.Request.Form) 
      { 
       if (ctl.EndsWith(".x") || ctl.EndsWith(".y")) 
       { 
        ctrlStr = ctl.Substring(0, ctl.Length - 2); 
        c = page.FindControl(ctrlStr); 
       } 
       else 
       { 
        c = page.FindControl(ctl); 
       } 
       if (c is System.Web.UI.WebControls.CheckBox || 
       c is System.Web.UI.WebControls.CheckBoxList) 
       { 
        control = c; 
        break; 
       } 
      } 
     } 
     return control; 
    } 

Тогда я изменить событие OnPreInit искать управления с идентификатором LinkButton или идентификатором, который содержит «опции»:

protected override void OnPreInit(EventArgs e) 
    { 
     base.OnPreInit(e); 
     System.Web.UI.MasterPage m = Master; 
     Control control = GetPostBackControl(this); 
     if (control != null) 
     { 
      if ((control.ClientID == (lbAddAndCondtion.ClientID) || createAgain) || control.ID.Contains("options")) 
      { 
       createAgain = true; 
       CreateUserControl(control.ID); 
      } 
     } 
    } 

Критическое исправление было в методе CreateUserControl. В моем исходном коде я пытался напрямую загрузить пользовательский элемент управления из моего общего списка, который был сохранен в сеансе.Я изменил, что на самом деле создать новый экземпляр пользовательского элемента управления, назначить этот новый экземпляр идентификатора, который соответствует одному хранящимся в сессии, а затем добавить его в заполнитель:

protected void CreateUserControl(string controlID) 
    { 
     try 
     { 
      if (createAgain && phConditions != null) 
      { 
       if (OptionControls.Count > 0) 
       { 
        phConditions.Controls.Clear(); 
        foreach (var c in OptionControls) 
        { 
         FilterOptionsCollectionView foc = new FilterOptionsCollectionView(); 
         foc = Page.LoadControl("~/Views/FilterOptionsCollectionView.ascx") as FilterOptionsCollectionView; 
         foc.ID = c.ID; 
         phConditions.Controls.Add(foc); 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

Единственного, что я изменил в пользовательский элемент управления перемещал метод, который загружает мои выпадающие списки и подключает событие OnSelectedIndexChanged к событию OnInit. Теперь я могу динамически загружать столько экземпляров пользовательского элемента управления, который я хочу, и все события внутри пользовательского элемента управления правильно работают, и состояние сохраняется через обратную передачу!

Надеюсь, это поможет кому-то еще!

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