Échec du chargement de contrôle composite viewstate [duplicata]
-
25-09-2019 - |
Question
Cette question a déjà une réponse ici:
J'ai un contrôle composite qui contient un ensemble différent de contrôles enfants en fonction de la valeur de l'un de ses propriétés lors de l'exécution. Chaque fois qu'il ya un postback, je reçois l'erreur suivante:
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.
Je suis googler cette question et de changer l'ordre de mon enfant contrôles instanciation à plusieurs reprises sans succès. Quelqu'un peut-il me dire ce que je fais mal ici? Les contrôles au sein de la fonction de contrôle composite correctement par eux-mêmes sans erreur.
Voici le contrôle composite:
[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
}
La solution
Au moins un problème avec votre code dans CreateChildControls est qu'il est un mélange de création de commande et de données code de liaison. Cela ne convient pas, parce que ViewState est chargé entre la création de contrôle et de liaison de données!
Divisez votre code dans le code de création de contrôle (CreateChildControls) et les données du code de liaison, en cours d'exécution plus tard dans le cycle de vie de la page. L'événement de chargement est un bon endroit pour la liaison de données.
En outre vous assurer que CreateChildControls est vraiment appelé avant que vos commandes sont utilisées. Je préfère appeler EnsureChildControls dans la page d'initialisation.
Autres conseils
Erreur dit:
arbre de commande dans lequel est viewstate chargé doit correspondre à la commande arbre qui a été utilisé pour sauver viewstate
Cela signifie que si vous aviez un certain contrôle sur votre page pendant la sauvegarde de l'état d'affichage, alors il doit être là lors du chargement de l'état d'affichage après la publication. Je pense que vous devriez vérifier comment votre contrôle composite crée des contrôles enfants et assurez-vous qu'ils sont créés après la publication.