0

リンクボタンをクリックしたときに、そのページにUsercontrolを追加したいというページがあります。私は、ユーザーが望むだけ多くのコントロールを追加/削除できる必要があります。 Usercontrolは3つのドロップダウンリストで構成されています。最初のドロップダウンリストには、auotpostbackプロパティがtrueに設定されており、起動時に残りの2つのドロップダウンリストが適切な値でロードされるOnSelectedIndexChangedイベントがフックされます。状態を動的に保存するUserControls ...ヘルプ!

私の問題は、私は、ホストページにコードを置くに関係なく、ユーザーコントロールが正しくロードされていないことです。私はすべてのポストバックでusercontrolsを再作成しなければならないことを知っていて、私はホスティングページのOnPreInitメソッドで実行されているメソッドを作成しました。私はまだ次のエラーが発生しています: コントロールコレクションは、DataBind、Init、Load、PreRenderまたはUnloadフェーズでは変更できません。ここで

は私のコードです: ありがとうございました!!!!

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

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のコードです


namespace Insight.Website.Views 

{[ViewStateModeById] パブリックパーシャルクラスFilterOptionsCollectionView:System.Web.UI.UserControl {保護されたボイドをPage_Load(オブジェクト送信者、の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; } 
} 

}

答えて

1

私はそれを理解しました。私の解決策は次のとおりです。

GetPostBackControlを変更して、ユーザーコントロールを挿入するlinkbuttonだけでなく、挿入されたユーザーコントロールの子コントロールのIDを含むコントロールを探します(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; 
    } 

それから私は、LinkBut​​tonコントロールまたは「オプション」が含まIDのIDを持つコントロールを探すためにOnPreInitイベントを変更:

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

私が変更さ唯一の事:私は実際にユーザーコントロールの新しいインスタンスを作成するには、その新しいインスタンスをセッションに保存されているものと一致するIDを割り当てて、その後、プレースホルダに追加することを変更しましたユーザーコントロールは、ドロップダウンリストをロードし、OnSelectedIndexChangedイベントをOnInitイベントに配線するメソッドを移動していました。これで、必要なユーザーコントロールのインスタンスを動的にロードすることができ、ユーザーコントロール内のすべてのイベントが正しく起動され、状態がポストバック間で維持されます。

これは他の人に役立つことを願っています。

関連する問題