2010-10-23 66 views
0

我有一個複合控件,它包含一組不同的子控件,這些控件基於它在運行時的某個屬性的值。 每當有一個回傳,我收到以下錯誤:無法加載視圖狀態複合控件

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. 

我一直在谷歌上搜索這個問題,並改變了我的孩子的順序反覆控制實例沒有成功。任何人都可以告訴我我在這裏做錯了什麼?複合控制內的控制功能正確無誤。

這裏是複合控件:

[Serializable] 
public enum AddEditType 
{ 
    SelectList, 
    SelectSingleItem, 
    SelectSingleItemWithForm, 
    Form 
} 
[Themeable(true)] 
[Serializable] 
public class AddEdit<TBO, TCriteria> : CompositeControl 
    where TBO : Bll.BOBase 
    where TCriteria : Bll.BaseCriteria 
{ 
    #region Constructor 
    public AddEdit(ObjectType myObjectType, AddEditType myType, EquatableList<TBO> myDataList, EditPageViewType myViewType) 
    { 
     this.ObjectType = myObjectType; 
     this.Type = myType; 
     this.myViewType = myViewType; 
     cachedOriginalList = myDataList.Clone(); 
     cachedCurrentList = myDataList.Clone(); 
    } 
    #endregion 

    #region Private Fields 
    private EditPageViewType myViewType = EditPageViewType.Read; 
    private EquatableList<TBO> cachedOriginalList 
    { 
     get 
     { 
      // Get reference to cache 
      ICacheManager cache = CacheFactory.GetCacheManager(); 
      // Look for cached data. 
      string cacheKey = GenerateCacheKey("cachedOriginalList"); 
      EquatableList<TBO> myList = (EquatableList<TBO>)cache.GetData(cacheKey); 
      return myList; 
     } 
     set 
     { 
      // Get reference to cache 
      ICacheManager cache = CacheFactory.GetCacheManager(); 
      // Store the value in the cache. 
      string cacheKey = GenerateCacheKey("cachedOriginalList"); 
      cache.Add(cacheKey, value); 
     } 
    } 
    private EquatableList<TBO> cachedCurrentList 
    { 
     get 
     { 
      // Get reference to cache 
      ICacheManager cache = CacheFactory.GetCacheManager(); 
      // Look for cached data. 
      string cacheKey = GenerateCacheKey("cachedCurrentList"); 
      EquatableList<TBO> myList = (EquatableList<TBO>)cache.GetData(cacheKey); 
      return myList; 
     } 
     set 
     { 
      // Get reference to cache 
      ICacheManager cache = CacheFactory.GetCacheManager(); 
      // Store the value in the cache. 
      string cacheKey = GenerateCacheKey("cachedCurrentList"); 
      cache.Add(cacheKey, value); 
     } 
    } 
    private Label myTitle; 
    private UpdatePanel myCurrentEntriesUpdatePanel; 
    private ButtonPanel myButtonPanel; 
    private MyCompanygridview myCurrentEntriesGridView; 
    private Panel myEditEntriesPanel; 
    private HiddenField myModalPopupTargetControl; 
    private ModalPopupExtender myEditEntriesPopup; 
    private UpdatePanel myEditEntriesUpdatePanel; 
    private Label myEditTitle; 
    private Panel myEditContentPanel; 
    private SearchGrid<TCriteria> mySearchGrid; 
    private Button myConfirmEditEntriesChangesButton; 
    private Button myCancelEditEntriesChangesButton; 
    private TCriteria mySearchCriteria; 

    #endregion 

    #region Public Properties 
    /// <summary> 
    /// Gets or sets the type of display that should be shown in the Add/Edit Control. 
    /// </summary> 
    /// <summary> 
    /// Gets or sets the type of display that should be shown in the Add/Edit Control. 
    /// </summary> 
    [Category("AddEdit"), 
    Description("Gets or sets the type of display that should be shown in the Add/Edit Control."), 
    DefaultValue(null)] 
    public AddEditType Type 
    { 
     get 
     { 
      return (AddEditType)ViewState["AddEditType"]; 
     } 
     set 
     { 
      ViewState["AddEditType"] = value; 
     } 

    } 
    /// <summary> 
    /// Gets or sets the type of items that should be shown in the Add/Edit Control. 
    /// </summary> 
    /// <summary> 
    /// Gets or sets the type of items that should be shown in the Add/Edit Control. 
    /// </summary> 
    [Category("AddEdit"), 
    Description("Gets or sets the type of items that should be shown in the Add/Edit Control."), 
    DefaultValue(null)] 
    public ObjectType ObjectType 
    { 
     get 
     { 
      return (ObjectType)ViewState["ObjectType"]; 
     } 
     set 
     { 
      ViewState["ObjectType"] = value; 
     } 

    } 
    public EquatableList<TBO> DataList 
    { 
     get 
     { 
      return cachedCurrentList; 
     } 
     set 
     { 
      cachedCurrentList = value; 
     } 
    } 
    /// <summary> 
    /// Gets or sets the search criteria. 
    /// </summary> 
    /// <value>The search criteria.</value> 
    public TCriteria SearchCriteria 
    { 
     get 
     { 
      return mySearchCriteria; 
     } 
     set 
     { 
      mySearchCriteria = value; 
     } 
    } 
    #endregion 
    #region Overridden Methods 
    protected override void RecreateChildcotrols() 
    { 
     EnsureChildcontrols(); 
    } 
    protected override void CreateChildControls() 
    { 
     Controls.Clear(); 

     ButtonPanelType myButtonPanelType = ButtonPanelType.SelectList; 
     string myEditEntriesTitle = "Select " + Enum.GetName(typeof(ObjectType), this.ObjectType) + ":"; 
     switch (Type) 
     { 
      case AddEditType.Form: 
       myButtonPanelType = ButtonPanelType.SelectList; 
       myEditEntriesTitle = "Edit " + Enum.GetName(typeof(ObjectType), this.ObjectType) + ":"; 
       break; 
      case AddEditType.SelectList: 
       myButtonPanelType = ButtonPanelType.SelectList; 
       myEditEntriesTitle = "Select " + Enum.GetName(typeof(ObjectType), this.ObjectType) + ":"; 
       mySearchGrid = new SearchGrid<TCriteria>(this.ObjectType); 
       break; 
      case AddEditType.SelectSingleItem: 
       myButtonPanelType = ButtonPanelType.SelectSingleItem; 
       myEditEntriesTitle = "Select " + Enum.GetName(typeof(ObjectType), this.ObjectType) + ":"; 
       mySearchGrid = new SearchGrid<TCriteria>(this.ObjectType); 
       break; 
      case AddEditType.SelectSingleItemWithForm: 
       myButtonPanelType = ButtonPanelType.SelectSingleItem; 
       myEditEntriesTitle = "Select/Edit " + Enum.GetName(typeof(ObjectType), this.ObjectType) + ":"; 
       mySearchGrid = new SearchGrid<TCriteria>(this.ObjectType); 
       break; 
     } 


     AddEditParser parser = AddEditParserFactory.GetParser(this.ObjectType); 

     // Define the Title Label 
     myTitle = new Label(); 
     this.Controls.Add(myTitle); 
     myTitle.ID = "lblTitle"; 
     myTitle.Text = Enum.GetName(typeof(ObjectType), this.ObjectType) + ":"; 

     // Define the Current Entries Update Panel 
     myCurrentEntriesUpdatePanel = new UpdatePanel(); 
     this.Controls.Add(myCurrentEntriesUpdatePanel); 
     myCurrentEntriesUpdatePanel.ID = "updpnlCurrentEntries"; 
     myCurrentEntriesUpdatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional; 


     // Define the Button Panel 
     myButtonPanel = new ButtonPanel(myButtonPanelType, myViewType); 
     myButtonPanel.AddButtonClick += new EventHandler(myButtonPanel_AddButtonClick); 
     myButtonPanel.ResetButtonClick += new EventHandler(myButtonPanel_ResetButtonClick); 
     myButtonPanel.RemoveSelectedButtonClick += new EventHandler(myButtonPanel_RemoveSelectedButtonClick); 
     myCurrentEntriesUpdatePanel.ContentTemplateContainer.Controls.Add(myButtonPanel);    

     // Define the Current Entries MyCompanygridView using parser 
     // and add it to the content template of the updatepanel. 
     myCurrentEntriesGridView = new MyCompanygridview(); 
     parser.CreateGridViewColumns(ref myCurrentEntriesGridView); 
     myCurrentEntriesUpdatePanel.ContentTemplateContainer.Controls.Add(myCurrentEntriesGridView); 
     myCurrentEntriesGridView.ID = "gvCurrentEntries"; 
     myCurrentEntriesGridView.AutoGenerateColumns = false; 
     myCurrentEntriesGridView.DataKeyNames = new string[] { "ID" }; 
     myCurrentEntriesGridView.DataSource = cachedCurrentList; 
     myCurrentEntriesGridView.AllowSorting = true; 
     myCurrentEntriesGridView.Width = new System.Web.UI.WebControls.Unit("100%"); 
     myCurrentEntriesGridView.AllowPaging = true; 
     myCurrentEntriesGridView.EnableCustomPager = true; 
     myCurrentEntriesGridView.SelectionType = MyCompanygridviewSelectionType.Multiple; 



     // Define the Edit Entries Panel 
     myEditEntriesPanel = new Panel(); 
     this.Controls.Add(myEditEntriesPanel); 
     myEditEntriesPanel.ID = "pnlEditEntries"; 
     myEditEntriesPanel.CssClass = "modalWindow"; 


     // Define the HiddenField used as the TargetControlID 
     // for the ModalPopupExtender, and add it to the panel. 
     myModalPopupTargetControl = new HiddenField(); 
     myEditEntriesPanel.Controls.Add(myModalPopupTargetControl); 
     myModalPopupTargetControl.ID = "hfModalPopupTargetControl"; 


     // Define the ModalPopupExtender and add it to the panel. 
     myEditEntriesPopup = new ModalPopupExtender(); 
     myEditEntriesPanel.Controls.Add(myEditEntriesPopup); 
     myEditEntriesPopup.ID = "mpeEditEntries"; 
     myEditEntriesPopup.BackgroundCssClass = "modalBackground"; 
     myEditEntriesPopup.PopupControlID = "pnlEditEntries"; 
     myEditEntriesPopup.TargetControlID = "hfModalPopupTargetControl"; 



     // Define the Edit Entries Update Panel 
     myEditEntriesUpdatePanel = new UpdatePanel(); 
     myEditEntriesPanel.Controls.Add(myEditEntriesUpdatePanel); 
     myEditEntriesUpdatePanel.ID = "updpnlEditEntries"; 
     myEditEntriesUpdatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional; 


     // Define the Edit Entries Title 
     myEditTitle = new Label(); 
     myEditEntriesUpdatePanel.ContentTemplateContainer.Controls.Add(myEditTitle); 
     myEditTitle.ID = "lblEditTitle"; 
     myEditTitle.Text = myEditEntriesTitle; 


     // Define the Edit Entries Content 
     myEditContentPanel = new Panel(); 
     myEditEntriesUpdatePanel.ContentTemplateContainer.Controls.Add(myEditContentPanel); 
     myEditContentPanel.ID = "pnlEditContent"; 
     switch (Type) 
     { 
      case AddEditType.Form: 
       parser.CreateFormControls(ref myEditContentPanel, new Dictionary<SearchPanelControlType, string>()); 
       break; 
      case AddEditType.SelectList: 
       mySearchGrid = new SearchGrid<TCriteria>(this.ObjectType); 
       mySearchGrid.GridView.SelectionType = MyCompanygridviewSelectionType.Multiple; 
       mySearchGrid.SearchCriteria = this.mySearchCriteria; 
       myEditContentPanel.Controls.Add(mySearchGrid); 
       break; 
      case AddEditType.SelectSingleItem: 
       mySearchGrid = new SearchGrid<TCriteria>(this.ObjectType); 
       mySearchGrid.GridView.SelectionType = MyCompanygridviewSelectionType.Single; 
       mySearchGrid.SearchCriteria = this.mySearchCriteria; 
       myEditContentPanel.Controls.Add(mySearchGrid); 
       break; 
      case AddEditType.SelectSingleItemWithForm: 
       mySearchGrid = new SearchGrid<TCriteria>(this.ObjectType); 
       mySearchGrid.GridView.SelectionType = MyCompanygridviewSelectionType.Single; 
       mySearchGrid.SearchCriteria = this.mySearchCriteria; 
       myEditContentPanel.Controls.Add(mySearchGrid); 
       parser.CreateFormControls(ref myEditContentPanel, new Dictionary<SearchPanelControlType, string>()); 
       break; 
     } 

     // Define the Confirm/Cancel buttons 
     myConfirmEditEntriesChangesButton = new Button(); 
     myConfirmEditEntriesChangesButton.Click += new EventHandler(myConfirmEditEntriesChangesButton_Click); 
     myEditEntriesUpdatePanel.ContentTemplateContainer.Controls.Add(myConfirmEditEntriesChangesButton); 
     myConfirmEditEntriesChangesButton.ID = "btnConfirmEditEntriesChanges"; 
     myConfirmEditEntriesChangesButton.Text = "Save"; 
     myConfirmEditEntriesChangesButton.CausesValidation = true; 


     myCancelEditEntriesChangesButton = new Button(); 
     myCancelEditEntriesChangesButton.Click += new EventHandler(myCancelEditEntriesChangesButton_Click); 
     myEditEntriesUpdatePanel.ContentTemplateContainer.Controls.Add(myCancelEditEntriesChangesButton); 
     myCancelEditEntriesChangesButton.ID = "btnCancelEditEntriesChanges"; 
     myCancelEditEntriesChangesButton.Text = "Cancel"; 
     myCancelEditEntriesChangesButton.CausesValidation = true; 




     ConfigureDisplay(); 
    } 


    //protected override void Render(HtmlTextWriter writer) 
    //{ 
    // AddAttributesToRender(writer); 

    // writer.RenderBeginTag(HtmlTextWriterTag.Div); 

    // myTitle.RenderControl(writer); 
    // myCurrentEntriesUpdatePanel.RenderControl(writer); 
    // myEditEntriesPanel.RenderControl(writer); 

    // writer.RenderEndTag(); 
    //} 
    #endregion 

    #region Public Event Handlers 
    #region Make the OnCancel event of the AddEdit control visible 
    private static readonly object EventCancelEditKey = new object(); 
    public event EventHandler CancelEdit 
    { 
     add 
     { 
      Events.AddHandler(EventCancelEditKey, value); 
     } 
     remove 
     { 
      Events.RemoveHandler(EventCancelEditKey, value); 
     } 
    } 
    protected virtual void OnCancelEdit(EventArgs e) 
    { 
     EventHandler CancelEditHandler = (EventHandler)Events[EventCancelEditKey]; 
     if (CancelEditHandler != null) 
     { 
      CancelEditHandler(this, e); 
     } 
    } 
    private void myCancelEditEntriesChangesButton_Click(object source, EventArgs e) 
    { 
     myEditEntriesPopup.Hide(); 
     ResetEditEntriesControls(); 
     OnCancelEdit(EventArgs.Empty); 
    } 
    #endregion 
    #region Make the OnConfirmEdit event of the AddEdit control visible 
    private static readonly object EventConfirmEditKey = new object(); 
    public event EventHandler ConfirmEdit 
    { 
     add 
     { 
      Events.AddHandler(EventConfirmEditKey, value); 
     } 
     remove 
     { 
      Events.RemoveHandler(EventConfirmEditKey, value); 
     } 
    } 
    protected virtual void OnConfirmEdit(EventArgs e) 
    { 
     EventHandler ConfirmEditHandler = (EventHandler)Events[EventConfirmEditKey]; 
     if (ConfirmEditHandler != null) 
     { 
      ConfirmEditHandler(this, e); 
     } 
    } 
    private void myConfirmEditEntriesChangesButton_Click(object source, EventArgs e) 
    { 

     if (Type != AddEditType.Form) 
     { 
      EquatableList<TBO> myOldList = cachedCurrentList.Clone(); 

      try 
      { 
       List<Guid> mySelectedValues = mySearchGrid.GridView.SelectedValues; 

       // Add each item in the SelectedValues list 
       // to the cachedCurrentList 
       foreach (Guid currentGUID in mySelectedValues) 
       { 
        ObjectMetaDataDictionary myOMD = ObjectMetaDataDictionary.Instance; 
        Type _objectType = myOMD[this.ObjectType].BOClass; 

        TBO myObject = (TBO)Activator.CreateInstance(_objectType); 

        // Check to see if it already exists in the 
        // cachedCurrentList. If it doesn't, add it. 
        if (!cachedCurrentList.ExistByID<TBO>(currentGUID)) 
        { 
         Type _managerType = myOMD[this.ObjectType].ManagerClass; 
         Object[] myStaticMethodArguments = new Object[1]; 
         myStaticMethodArguments.SetValue(currentGUID, 0); 
         MethodInfo myStaticMethodInfo = _managerType.GetMethod("GetItem"); 
         myObject = (TBO)myStaticMethodInfo.Invoke(null, myStaticMethodArguments); 


         // If the Object is not null add it to the cachedCurrentList. 
         if (myObject != null) 
         { 
          cachedCurrentList.Add(myObject); 
         } 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       cachedCurrentList = myOldList.Clone(); 
       bool rethrow = ExceptionPolicy.HandleException(ex, "Base Policy"); 
       if (rethrow) 
       { 
        StringBuilder sb = new StringBuilder(); 
        sb.AppendFormat("Error: {0}", ex.Message); 
       } 
      } 
     } 



     myEditEntriesPopup.Hide(); 
     BindCurrentGrid(); 
     myCurrentEntriesUpdatePanel.Update(); 
     ResetEditEntriesControls(); 
     OnConfirmEdit(EventArgs.Empty); 
    } 
    #endregion 
    #endregion 

    #region Private Event Handlers 

    #endregion 

    #region Private Methods 
    /// <summary> 
    /// Creates a string used to identify this control in the cache. 
    /// </summary> 
    private string GenerateCacheKey(string key) 
    { 
     StringBuilder sb = new StringBuilder(); 
     sb.AppendFormat("{0}:{1}:{2}:{3}", "AddEditControl", Enum.GetName(typeof(ObjectType), this.Type), this.Context.Session.SessionID, key); 
     return sb.ToString(); 
    } 
    private void BindCurrentGrid() 
    { 
     myCurrentEntriesGridView.DataSource = cachedCurrentList; 
     myCurrentEntriesGridView.DataBind(); 

    } 
    protected void myButtonPanel_AddButtonClick(object sender, EventArgs e) 
    { 
     myEditEntriesPopup.Show(); 
    } 
    protected void myButtonPanel_ResetButtonClick(object sender, EventArgs e) 
    { 
     cachedCurrentList = cachedOriginalList.Clone(); 
     BindCurrentGrid(); 
     myCurrentEntriesUpdatePanel.Update(); 
     ResetEditEntriesControls(); 
     myEditEntriesUpdatePanel.Update(); 
    } 
    protected void myButtonPanel_RemoveSelectedButtonClick(object sender, EventArgs e) 
    { 
     EquatableList<TBO> myOldList = cachedCurrentList.Clone(); 

     try 
     { 
      List<Guid> mySelectedValues = mySearchGrid.GridView.SelectedValues; 
      // Remove each item in the SelectedValues list from the cachedCurrentList 
      foreach (Guid currentGUID in mySelectedValues) 
      { 
       cachedCurrentList.RemoveAll(delegate(TBO x) { return x.Id == currentGUID; }); 
      } 
      BindCurrentGrid(); 
      myCurrentEntriesUpdatePanel.Update(); 
      ResetEditEntriesControls(); 
     } 
     catch (Exception ex) 
     { 
      cachedCurrentList = myOldList.Clone(); 
      bool rethrow = ExceptionPolicy.HandleException(ex, "Base Policy"); 
      if (rethrow) 
      { 
       StringBuilder sb = new StringBuilder(); 
       sb.AppendFormat("Error: {0}", ex.Message); 
      } 
     } 
    } 
    private void ResetEditEntriesControls() 
    { 
     if (Type != AddEditType.Form) 
     { 
      // RESET SEARCH GRID 
      mySearchGrid.GridView.SelectedValues = cachedOriginalList.ToListOfIDs(); 
      if (typeof(IDisabledFlg).IsAssignableFrom(typeof(TBO))) 
      { 
       foreach (TBO item in cachedOriginalList) 
       { 
        IDisabledFlg castedItem = (IDisabledFlg)item; 
        if (castedItem.DisabledFlg) 
        { 
         mySearchGrid.GridView.DisabledValues.Add(castedItem.Id); 
        } 
       } 
      } 
      mySearchGrid.GridView.DataBind(); 
      mySearchGrid.SearchCriteria = this.mySearchCriteria; 
     } 
     if (Type == AddEditType.Form || Type == AddEditType.SelectSingleItemWithForm) 
     { 
      // Call parser to reset any other controls 
      AddEditParser parser = AddEditParserFactory.GetParser(this.ObjectType); 
      parser.SetFormControls<TBO>(null, ref myEditEntriesPanel); 
     } 
    } 
    private void ConfigureDisplay() 
    { 
     myButtonPanel.ViewType = this.myViewType; 
     switch (myViewType) 
     { 
      case EditPageViewType.Update: 
       myCurrentEntriesGridView.Enabled = true; 
       break; 
      case EditPageViewType.Create: 
       myCurrentEntriesGridView.Enabled = true; 
       break; 
      case EditPageViewType.Read: 
       myCurrentEntriesGridView.Enabled = false; 
       break; 
      case EditPageViewType.Disable: 
       myCurrentEntriesGridView.Enabled = false; 
       break; 
     } 
    } 
    #endregion 
} 

回答

0

CreateChildControls中的代碼至少有一個問題,它是控件創建和數據綁定代碼的混合。這是不合適的,因爲ViewState在控件創建和數據綁定之間加載!

在控制創建代碼(CreateChildControls)和數據綁定代碼中拆分代碼,稍後在頁面生命週期中運行。加載事件是數據綁定的好地方。

進一步確保在使用控件之前確實調用了CreateChildControls。我更喜歡在頁面init中調用EnsureChildControls。

0

錯誤說:

control tree into which viewstate is being loaded must match the control tree that was used to save viewstate

這意味着,如果你在保存視圖狀態的有你的頁面上的一些控制,那麼它必須在那裏回發後視圖狀態的負載。我認爲你應該檢查你的複合控件如何創建子控件,並確保它們是在回發後創建的。

+0

嗯,我一直在遍歷代碼,它似乎在回發上運行「CreateChildControls()」方法。確定應創建哪些控件的值在回發期間不會更改。換句話說,它不會動態地改變回發時的控件集合,只有當它初次被初始化時。 – 2010-10-23 16:22:57