By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,269 Members | 1,507 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,269 IT Pros & Developers. It's quick & easy.

ListBox inside UserControl ViewState lost

P: 3
Hi, everybody. I have this problem. When I put a <asp:ListBox on a web page and populate the data in the page Page_Load event the ViewState for the control is saved and loaded (after postback) correctly. In other words the Items property of the ListBox is populated from the ViewState after the postback. However if I put this ListBox inside a UserControl, expose the Items list, and populate it with the data in the same manner (in the page Page_Load event), the data is lost after the postback. What is wrong?

Here is the code with viewstate working:

Page:
Expand|Select|Wrap|Line Numbers
  1. <html xmlns="http://www.w3.org/1999/xhtml">
  2. <body>
  3. <form id="MainForm" runat="server">
  4.    <asp:ListBox ID="ctrlDynList" runat="server" />
  5.    <br />
  6.    <asp:Button ID="btnSubmit" Text="Submit" onclick="btnSubmit_Click" runat="server" />
  7. </form>
  8. </body>
  9. </html>
  10.  
Code behind:
...
Expand|Select|Wrap|Line Numbers
  1.    public partial class MultiSelect : Page {
  2.       protected void Page_Load(object sender, EventArgs e) {
  3.          if(!IsPostBack) {
  4.             ctrlDynList.Items.Add(new ListItem("One", "1"));
  5.             ctrlDynList.Items.Add(new ListItem("Two", "2"));
  6.          }
  7.       }
  8. ...
  9. }
Here is the code with viewstate not working:

Page:
Expand|Select|Wrap|Line Numbers
  1. <%@ Register Src="~/Test/SimplePanel.ascx" TagPrefix="uc" TagName="SimplePanel" %>
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <body>
  4. <form id="MainForm" runat="server">
  5.    <uc:SimplePanel ID="ctrlDynList" runat="server" />
  6.    <br />
  7.    <asp:Button ID="btnSubmit" Text="Submit" onclick="btnSubmit_Click" runat="server" />
  8. </form>
  9. </body>
  10. </html>
Code behind:
...
Expand|Select|Wrap|Line Numbers
  1.    public partial class MultiSelect : Page {
  2.       protected void Page_Load(object sender, EventArgs e) {
  3.          if(!IsPostBack) {
  4.             ctrlDynList.Items.Add(new ListItem("One", "1"));
  5.             ctrlDynList.Items.Add(new ListItem("Two", "2"));
  6.          }
  7.          else {
  8. // The ctrlDynList.Items is empty in this case.
  9. // It is not loaded from the viewstate like it does
  10. // in the case when the ListBox is placed on the page (not inside a user control)
  11.          }
  12.       }
  13. ...
  14. }
User control:
Expand|Select|Wrap|Line Numbers
  1. <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SimplePanel.ascx.cs" Inherits="MgScopes.MgScopesWeb.Test.SimplePanel" %>
  2. <asp:ListBox ID="ctrlListBox" runat="server" />
  3.  
Code behind:
...
Expand|Select|Wrap|Line Numbers
  1.    public partial class SimplePanel : UserControlBase {
  2.       protected void Page_Load(object sender, EventArgs e) {
  3.       }
  4.  
  5.       public ListItemCollection Items {
  6.          get { return ctrlListBox.Items; }
  7.       }
  8.    }
  9. ...
  10. }
Jul 23 '09 #1
Share this Question
Share on Google+
6 Replies


maliksleo
100+
P: 115
place your page_load event on the user control page not on main page and check your problem will be solved.

maliksleo
Jul 24 '09 #2

P: 3
I tried all those kind of things. I finally found the answer I could never think on. In completely separate part of my code, not concerned to this sample, I called Controls.AddAt(Number, Control). This call blows ViewState for all controls in the collection and it seems like not only in this collection (I didn't investigate futher). It looks like the Framework keeps control's positions deep inside and if the positions change it cannot bind the ViewState to the controls. So, basically, if you care about the ViewState never call AddAt. Call Controls.Add instead. It works fine.
Jul 24 '09 #3

Frinavale
Expert Mod 5K+
P: 9,731
It doesn't really matter how you fill the control you should not be experiencing this.
Maliksleo's suggestion is good because it makes more sense to make the user control responsible for maintaining the list.

I tested what you posted and could not reproduce your problem.

This is what I have.

The user control:
Expand|Select|Wrap|Line Numbers
  1. <%@ Control Language="vb" AutoEventWireup="false" CodeBehind="ctrl.ascx.vb" Inherits="ScratchPad.ctrl" %>
  2. <div>
  3.     <asp:ListBox ID="theList" runat="server" AutoPostBack="true"></asp:ListBox>
  4.     <asp:Label ID="selectedItem" runat="server"></asp:Label>
  5. </div>
The code behind for the user control:
Expand|Select|Wrap|Line Numbers
  1. Public Partial Class ctrl
  2.     Inherits System.Web.UI.UserControl
  3.     Public ReadOnly Property Items() As ListItemCollection
  4.         Get
  5.             Return theList.Items
  6.         End Get
  7.     End Property
  8.  
  9.     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  10.  
  11.     End Sub
  12.  
  13.     Private Sub theList_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles theList.SelectedIndexChanged
  14.         Dim selectedItemText As String = theList.SelectedItem.Text
  15.         selectedItem.Text = selectedItemText
  16.     End Sub
  17. End Class
The aspx page:
Expand|Select|Wrap|Line Numbers
  1. <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm3.aspx.vb" Inherits="ScratchPad.WebForm3" %>
  2. <%@ Register TagPrefix="uc" TagName="ListUserControl" Src="~/ctrl.ascx" %>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head runat="server">
  6.   <title></title>
  7. </head>
  8. <body>
  9.     <form id="form1" runat="server">
  10.     <uc:ListUserControl runat="server" ID="theListControl" />
  11.     </form>
  12. </body>
  13. </html>
  14.  
The code behind for the aspx page:
Expand|Select|Wrap|Line Numbers
  1. Partial Public Class WebForm3
  2.     Inherits System.Web.UI.Page
  3.     Private _gridViewDataSource As DataView
  4.     Private _detailsSource As DataSet
  5.  
  6.     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  7.         If IsPostBack = False Then
  8.             theListControl.Items.Add(New ListItem("First Item", "1"))
  9.             theListControl.Items.Add(New ListItem("Second Item", "2"))
  10.         End If
  11.      End Sub
  12. End Class
Like I said, this works perfectly fine.
Jul 24 '09 #4

Frinavale
Expert Mod 5K+
P: 9,731
@kucheravy
Oh! I see what the problem is.

If you're calling the ControlCollection.AddAt() method then you're probably dynamically adding controls to your page. You did not mention this fact in your explanation of the problem...in fact your example code doesn't show you dynamically adding the control at all.

The reason the ViewState isn't being remembered in your case is because of how the ASP Page Life Cycle works...

This is what's happening:

The web browser makes a request for the page.

The Page Init Event occurs and all of the Objects required to do page processing are created.

Right After the Page Init Event the ViewState of the controls are loaded.

If your dynamically creating controls in the Page Load (or after that in the life cycle) then the ViewState for the control is not loaded because the Object doesn't exist!

So, if you want the ViewState to load for dynamic controls, then you'll have to instantiate them (use the "new" statement) in the Page Init event. You also have to add them to their appropriate containers at this point too or you're going to experience a validation exception.
Jul 24 '09 #5

P: 3
I agree with your explanation and I new that. The problem is that as soon as you use Constrols.AddAt no controls that were already statically created and loaded into the Controls could Save/Load their state. It is not a problem of that one control that I add dynamically by AddAt. The whole collection of the controls loses the viewstate. BUT if you use Add everything is fine for the whole colleciton and that dynamically added control. I just wanted to state this problem for other people who might have the similar problem. I wasted a day figuring this out.
Jul 24 '09 #6

Frinavale
Expert Mod 5K+
P: 9,731
Hmm I've never used the AddAt method before. I've always used the Add method.

I guess it makes sense that it would mess up the static controls when you use the AddAt method though...because something else (a static control) could be at that index.

Thanks for added the info :)

-Frinny
Jul 25 '09 #7

Post your reply

Sign in to post your reply or Sign up for a free account.