0

Ich habe Seite mit einem LinkButton darauf, dass wenn ich geklickt habe, möchte ich eine Benutzersteuerung der Seite hinzufügen. Ich muss in der Lage sein, so viele Steuerelemente hinzuzufügen/zu entfernen, wie der Benutzer es wünscht. Die Benutzersteuerung besteht aus drei Dropdown-Listen. In der ersten Dropdownliste ist die Eigenschaft auotpostback auf true festgelegt und verknüpft das OnSelectedIndexChanged-Ereignis, das beim Löschen die verbleibenden zwei Dropdownlisten mit den entsprechenden Werten lädt.Speichern von dynamischen Benutzersteuerelementen ... Hilfe!

Mein Problem ist, dass egal, wo ich den Code auf der Host-Seite, die Benutzersteuerung nicht richtig geladen wird. Ich weiß, ich muss die Benutzersteuerelemente auf jedem Postback neu erstellen, und ich habe eine Methode erstellt, die in der OnPreInit-Methode der Host-Seiten ausgeführt wird. Ich erhalte immer noch den folgenden Fehler: Die Steuerelementauflistung kann nicht während der Phasen DataBind, Init, Load, PreRender oder Unload geändert werden.

Hier ist mein Code: Vielen Dank !!!!

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; 
     } 
    } 

Hier ist der Code des Usercontrol:

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


namespace Insight.Website.Views 

{ [ViewStateModeById] public partial class FilterOptionsCollectionView: System.Web.UI.UserControl { protected void Page_Load (object sender, EventArgs e) {

} 

    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; } 
} 

}

Antwort

1

Ich fand es heraus. Hier ist meine Lösung:

Ich modifizierte die GetPostBackControl, um nicht nur die Verknüpfungsschaltfläche zu suchen, die das Benutzersteuerelement einfügt, sondern für Steuerelemente, die die ID der untergeordneten Steuerelemente des eingefügten Benutzersteuerelements enthalten (um OnSelectedIndexChanged zu erfassen, das ausgelöst wird) von innen meine Benutzerkontrolle).

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; 
    } 

dann die OnPreInit Ereignis, das ich ändern für die Kontrollen mit der ID des Linkbutton oder eine ID zu suchen, die „Optionen“ enthält:

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); 
      } 
     } 
    } 

Die kritische fix war in der CreateUserControl Methode. In meinem ursprünglichen Code habe ich versucht, das Benutzersteuerelement direkt aus meiner generischen Liste zu laden, die in Session gespeichert wurde.Ich änderte, dass tatsächlich eine neue Instanz der Benutzersteuerung erstellen, weisen die neue Instanz eine Kennung, die eine in Session gespeichert einstimmt, und dann auf den Platzhalter hinzufügen:

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; 
     } 
    } 

Das einzige, was ich in der geändert Benutzersteuerelement bewegte die Methode, die meine Dropdown-Listen lädt und das OnSelectedIndexChanged-Ereignis in das OnInit-Ereignis verdrahtet. Jetzt kann ich dynamisch so viele Instanzen des Benutzersteuerelements laden, das ich will, und alle Ereignisse innerhalb des Benutzersteuerelements werden korrekt ausgelöst und der Status wird über Postbacks beibehalten.

Hoffe das hilft jemand anderen !!