views:

545

answers:

2

First off, I am not dynamically creating any controls. This is the order I take to produce the error:

I have a listview on the page, when I click the edit link under the listview, I display a panel which is hidden by default. The panel has a few buttons on it along with some listboxes. When I click an item in the listbox or click one of the buttons, I get the following error:

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.

Again, I am not creating anything dynamically, I am just hiding the panel with the controls by default and then displaying them, so I am not sure why I am getting this error.

Here is some code:

PAGE LOAD

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        Session["Albums"] = null;
        Albums = AlbumCollection.GetAlbums(Common.GetUserName(), 
                                                       ddlAlbumType.SelectedIndex);

        lvwAlbums.DataSource = Albums;
        lvwAlbums.DataBind();
     }
}

When I click the edit link, this is the code that runs:

protected void lvwAlbums_RowEditing(object sender, ListViewEditEventArgs e)
{
    this.AlbumId = int.Parse(         
    this.lvwAlbums.DataKeys[e.NewEditIndex].Values["AlbumId"].ToString());

    this.AlbumName=
    this.lvwAlbums.DataKeys[e.NewEditIndex].Values["AlbumName"].ToString();

    Album album = new Album(this.AlbumId);

    ViewState["AlbumId"] = this.AlbumId;
    ViewState["AlbumName"] = this.AlbumName;

    pnlAlbum.Visible = true; // This panel holds the controls
    btnEditAlbum.Visible = true;
    btnCancel.Visible = true;
    EditAlbum(this.AlbumId);

        this.lvwAlbums.EditIndex = e.NewEditIndex;
        AlbumCollection.GetAlbums(Common.GetUserName(),ddlAlbumType.SelectedIndex);
    }

If I click the cancel button, I get the error, but it also happens if click another button on the panel such as Add/Remove... Here is the code for the Cancel button:

pnlAlbum.Visible = false;
this.lvwAlbums.EditIndex = -1;
AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);

Here is the aspx/html for the ListView:

<asp:ListView ID="lvwAlbums" 
              runat="server" 
              GroupItemCount="5" 
              DataKeyNames="AlbumId,AlbumName"
              OnItemEditing="lvwAlbums_RowEditing" 
              OnItemCommand="lvwAlbums_ItemCommand"
              OnItemDeleting="lvwAlbums_RowDeleting"  
              OnSelectedIndexChanging="lvwAlbums_SelectedIndexChanging"
              OnPagePropertiesChanging="lvwAlbums_PagePropertiesChanging">
 <EditItemTemplate>
 <td>
 <div>
 <asp:TextBox ID="txtAlbumName" runat="server"
              Text='<%# Eval("AlbumName").ToString().Trim() %>' />

 <asp:LinkButton ID="lnkView" runat="server" Text="View" CommandName="View"
                 CommandArgument='<%# Eval("AlbumId") %>'>
 </asp:LinkButton>
 |
 <asp:LinkButton ID="lnkEdit" runat="server" Text="Edit" CommandName="Edit"
                 CommandArgument='<%# Eval("AlbumId") %>'>
 </asp:LinkButton>
 |
 <asp:LinkButton ID="lnkDelete" runat="server" Text="Delete" CommandName="Delete"
                 CommandArgument='<%# Eval("AlbumId") %>'>
 </asp:LinkButton>
 <br />
 <span>Songs:
 <%# Eval("total") %></span>
 </div>
 </td>
 </EditItemTemplate>
 <LayoutTemplate>
 <asp:DataPager runat="server" ID="ItemDataPager" PageSize="20" 
                PagedControlID="lvwAlbums">
 <Fields>
 <asp:NumericPagerField ButtonType="Link" NumericButtonCssClass="pager" />
 </Fields>
 </asp:DataPager>
 <table>
 <tr>
 <td>
 <table>
 <asp:PlaceHolder runat="server" ID="groupPlaceHolder"></asp:PlaceHolder>
 </table>
 </td>
 </tr>
 </table>
 </LayoutTemplate>
 <GroupTemplate>
 <tr>
 <asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
 </tr>
 </GroupTemplate>
 <ItemTemplate>
 <td>
 <asp:Literal ID="litAlbumName" runat="server" 
              Text='<%#  Eval("AlbumName").ToString().Trim() %>' />
 <br />
 <asp:LinkButton ID="lnkView" runat="server" Text="View" CommandName="View"
                 CommandArgument='<%# Eval("AlbumId") %>'>
 </asp:LinkButton>
 |
 <asp:LinkButton ID="lnkEdit" runat="server" Text="Edit" CommandName="Edit"
                 CommandArgument='<%# Eval("AlbumId") %>'>
 </asp:LinkButton>
 |
 <asp:LinkButton ID="lnkDelete" runat="server" Text="Delete" CommandName="Delete"
                 CommandArgument='<%# Eval("AlbumId") %>'>
 </asp:LinkButton>
 <br />
 <span>Songs:
 <%# Eval("total") %></span>
 </td>
 </ItemTemplate>
 </asp:ListView>

Here is the markup for the Panel:

<asp:Panel ID="pnlAlbum" runat="server" Visible="false">
<asp:ListBox ID="lstAvailableSongs" runat="server" SelectionMode="Multiple">   
</asp:ListBox>
<asp:Button ID="btnAddAll" runat="server" Text="Add All" OnClick="btnAddAll_Click" />
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
<asp:Button ID="btnRemove" runat="server" Text="Remove" OnClick="btnRemove_Click" />
<asp:Button ID="btnRemoveAll" runat="server" 
            Text="Remove All"OnClick="btnRemoveAll_Click" />
<asp:ListBox ID="lstSelectedSongs" runat="server" SelectionMode="Multiple">  
</asp:ListBox>
<asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClick="btnCancel_Click" />
<asp:Button ID="btnEditAlbum" runat="server"Text="Save"
            ValidationGroup="CreateAlbum" OnClick="btnEditAlbum_Click" />
<asp:Button ID="btnSaveAs" runat="server" Text="Save As" ValidationGroup="CreateAlbum"
            OnClick="btnSaveAs_Click" />
</asp:Panel>

Here is some extra info:

I put an update panel around one of the listboxes in the panel and when I clicked the edit link under a listview item, I received the following error:

Microsoft JScript runtime error: Sys.InvalidOperationException: Could not find UpdatePanel with ID 'ctl00_ctl00_InnerContent_MainContent_UpdatePanel4'. If it is being updated dynamically then it must be inside another UpdatePanel.

Putting an UpdatePanel around the whole asp.net panel resolved the issue above, but I still get the Failed to load viewstate error when clicking on Cancel or Add, etc...

A: 

Question for you:

in your Page_Load you have

Albums = AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);

but in lvwAlbums_RowEditing(..) and in btnCancel_Click(...) you have

AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);

shouldn't these be (Albums = ...)

Albums = AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);
David Glass
+1  A: 

First off, you probably need to rebind the ListView after setting the EditIndex. (honestly, I haven't used ListView at all, but this is how the other repeater controls work) What does "EditAlbum()" do?

Your code is a little odd... why do you have the same controls in your EditItemTemplate as in the ItemTemplate? Ie, the Edit button should only be in the ItemTemplate... Then EditItemTemplate should have a Save or Cancel button.

Bottom line... your control tree is different on LoadViewState than it is when SaveViewState was called. One thing you can do is override these methods and then put a breakpoint there to manually look at the Controls collection in the debugger. You will probably see that the controls inside the ListView are different. But try my first suggestion before you do this.

Bryan