IE Web Controls Tabstrip and Corrupted ListBox ViewState Bug.

Discussion in 'ASP .Net Web Controls' started by Eric D. Wilson, Jun 30, 2005.

  1. I thought I'd post some info about a bug I've found in the way viewstate is
    handled (or not handled for that matter) when you dynamically remove a tab
    from the IE Web Control TabStrip control.

    I've got a web app that uses the tabstrip to partition various types of data
    with each tab corrosponding to a "feature". On each tab are several server
    controls including ListBoxes. Part of the business logic is that a user can
    select an item in a listbox and then click a button to initiate a post back.
    On the server I'd check to see what the select index value was and then
    provide a pop-up with details specific to the selected item (the pop-up is
    created using the RegisterClientScriptBlock() and a JavaScript function
    included in the page definition).

    When the page initially loads I check to see what features are
    enabled/disabled based on a setting in a database. When a feature is disabled
    I remove the tab that corrosponds to the feature from the tabstrip in the
    Page_Load() event. This only has to be done when IsPostBack is false as the
    viewstate will be maintained properly for the tabstrip itself.

    This is where the funny part starts.

    If there are ASP.NET ListBox controls on any of the subsequent tabs, their
    viewstate will be lost when a preceding tab is removed. I haven't tested
    every server control yet, but so far this behavior only appears to effect
    ListBox controls.

    I haven't taken the time to look through the code for the TabStrip,
    MultiPage, or PageView yet as I was able to come up with a work around.

    To work around the problem you can simply set the Enabled property of the
    disabled tab(s) to false. The tab will still be rendered but you won't be
    able to activate it.

    I've put together a demo of behavior using the tabstrip example that came
    with the IE web controls distribution. It's a little contrived but it shows
    the problem.

    Here's the source for my doctored "tabstrip.aspx" page.

    ************************************************************
    <%@ Register TagPrefix="iewc" Namespace="Microsoft.Web.UI.WebControls"
    Assembly="Microsoft.Web.UI.WebControls" %>
    <%@ Page language="c#" Codebehind="tabstrip.aspx.cs" AutoEventWireup="false"
    enableViewState="True" Trace="false" Inherits="IEWebCtrlSamples.tabstrip" %>
    <HTML>
    <body>
    <form runat="server">
    <iewc:TabStrip ID="tsTest" runat="server"
    TabDefaultStyle="background-color:#000000;font-family:verdana;font-weight:bold;font-size:8pt;color:#ffffff;width:79;height:21;text-align:center"
    TabHoverStyle="background-color:#777777"
    TabSelectedStyle="background-color:#ffffff;color:#000000"
    TargetID="mpTest">
    <iewc:Tab ID="tabHome" Text="Home" />
    <iewc:Tab ID="tabAboutUs" Text="About us" />
    <iewc:Tab ID="tabProducts" Text="Products" />
    <iewc:Tab ID="tabSupport" Text="Support" />
    <iewc:Tab ID="tabContactUs" Text="Contact us" />
    </iewc:TabStrip>
    <iewc:MultiPage id="mpTest" runat="server" Height="100%">
    <iewc:pageView id="pvHome">
    <asp:panel ID="panHome" Runat="server">
    <br />
    Home
    <br />
    <asp:ListBox ID="lstHome" Runat="server" Width="300px" Rows="10"
    EnableViewState="True"></asp:ListBox>
    <br />
    <asp:button id="btnHome" runat="server" Text="Post Back"></asp:button>
    </asp:panel>
    </iewc:pageView>
    <iewc:pageView id="pvAboutUs">
    <asp:panel ID="panAboutUs" Runat="server">
    <br />
    About Us
    <br />
    <asp:ListBox ID="lstAboutUs" Runat="server" Width="300px" Rows="10"
    EnableViewState="True"></asp:ListBox>
    <br />
    <asp:button id="btnAboutUs" runat="server" Text="Post
    Back"></asp:button>
    </asp:panel>
    </iewc:pageView>
    <iewc:pageView id="pvProducts">
    <asp:panel ID="panProducts" Runat="server">
    <br />
    Products
    <br />
    <asp:ListBox ID="lstProducts" Runat="server" Width="300px" Rows="10"
    EnableViewState="True"></asp:ListBox>
    <br />
    <asp:button id="btnProducts" runat="server" Text="Post
    Back"></asp:button>
    </asp:panel>
    </iewc:pageView>
    <iewc:pageView id="pvSupport">
    <asp:panel ID="panSupport" Runat="server">
    <br />
    Support
    <br />
    <asp:ListBox ID="lstSupport" Runat="server" Width="300px" Rows="10"
    EnableViewState="True"></asp:ListBox>
    <br />
    <asp:button id="btnSupport" runat="server" Text="Post
    Back"></asp:button>
    </asp:panel>
    </iewc:pageView>
    <iewc:pageView id="pvContactUs">
    <asp:panel ID="panContactUs" Runat="server">
    <br />
    Contact Us
    <br />
    <asp:ListBox ID="lstContactUs" Runat="server" Width="300px" Rows="10"
    EnableViewState="True"></asp:ListBox>
    <br />
    <asp:button id="btnContactUs" runat="server" Text="Post
    Back"></asp:button>
    </asp:panel>
    </iewc:pageView>
    </iewc:MultiPage>
    </form>
    </body>
    </HTML>

    ************************************************************

    Here's the source for the codebehind page that removes a tab.

    ************************************************************

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Diagnostics;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;

    namespace IEWebCtrlSamples
    {
    /// <summary>
    /// Summary description for WebForm1.
    /// </summary>
    public class tabstrip : System.Web.UI.Page
    {
    protected Microsoft.Web.UI.WebControls.TabStrip tsTest;
    protected Microsoft.Web.UI.WebControls.MultiPage mpTest;

    protected Microsoft.Web.UI.WebControls.Tab tabHome;
    protected Microsoft.Web.UI.WebControls.PageView pvHome;
    protected System.Web.UI.WebControls.Panel panHome;
    protected System.Web.UI.WebControls.ListBox lstHome;
    protected System.Web.UI.WebControls.Button btnHome;

    protected Microsoft.Web.UI.WebControls.Tab tabAboutUs;
    protected Microsoft.Web.UI.WebControls.PageView pvAboutUs;
    protected System.Web.UI.WebControls.Panel panAboutUs;
    protected System.Web.UI.WebControls.ListBox lstAboutUs;
    protected System.Web.UI.WebControls.Button btnAboutUs;

    protected Microsoft.Web.UI.WebControls.Tab tabProducts;
    protected Microsoft.Web.UI.WebControls.PageView pvProducts;
    protected System.Web.UI.WebControls.Panel panProducts;
    protected System.Web.UI.WebControls.ListBox lstProducts;
    protected System.Web.UI.WebControls.Button btnProducts;

    protected Microsoft.Web.UI.WebControls.Tab tabSupport;
    protected Microsoft.Web.UI.WebControls.PageView pvSupport;
    protected System.Web.UI.WebControls.Panel panSupport;
    protected System.Web.UI.WebControls.ListBox lstSupport;
    protected System.Web.UI.WebControls.Button btnSupport;

    protected Microsoft.Web.UI.WebControls.Tab tabContactUs;
    protected Microsoft.Web.UI.WebControls.PageView pvContactUs;
    protected System.Web.UI.WebControls.Panel panContactUs;
    protected System.Web.UI.WebControls.ListBox lstContactUs;
    protected System.Web.UI.WebControls.Button btnContactUs;

    private void Page_Load(object sender, System.EventArgs e)
    {
    if (!IsPostBack)
    {
    tsTest.Items.Remove(tabProducts);

    lstHome.Items.Add("Home 1");
    lstHome.Items.Add("Home 2");

    lstAboutUs.Items.Add("About Us 1");
    lstAboutUs.Items.Add("About Us 2");

    lstProducts.Items.Add("Products 1");
    lstProducts.Items.Add("Products 2");

    lstSupport.Items.Add("Support 1");
    lstSupport.Items.Add("Support 2");

    lstContactUs.Items.Add("Contact Us 1");
    lstContactUs.Items.Add("Contact Us 2");

    }

    panProducts.Visible = false;
    mpTest.Controls.Remove(pvProducts);

    // Put user code to initialize the page here
    Debug.WriteLine("Tab strip selected index: " + tsTest.SelectedIndex);
    }


    #region Web Form Designer generated code
    override protected void OnInit(EventArgs e)
    {
    //
    // CODEGEN: This call is required by the ASP.NET Web Form Designer.
    //
    InitializeComponent();
    base.OnInit(e);
    }

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
    this.Load += new System.EventHandler(this.Page_Load);

    this.btnHome.Click += new EventHandler(btnHome_Click);
    this.btnAboutUs.Click += new EventHandler(btnAboutUs_Click);
    this.btnProducts.Click += new EventHandler(btnProducts_Click);
    this.btnSupport.Click += new EventHandler(btnSupport_Click);
    this.btnContactUs.Click += new EventHandler(btnContactUs_Click);
    }
    #endregion

    private void btnHome_Click(object sender, EventArgs e)
    {
    Debug.WriteLine("Home post back button clicked.");
    Debug.WriteLine("List selected value: " + lstHome.SelectedValue);
    }

    private void btnAboutUs_Click(object sender, EventArgs e)
    {
    Debug.WriteLine("About Us post back button clicked.");
    Debug.WriteLine("List selected value: " + lstAboutUs.SelectedValue);
    }

    private void btnProducts_Click(object sender, EventArgs e)
    {
    Debug.WriteLine("Products post back button clicked.");
    Debug.WriteLine("List selected value: " + lstProducts.SelectedValue);
    }

    private void btnSupport_Click(object sender, EventArgs e)
    {
    Debug.WriteLine("Support post back button clicked.");
    Debug.WriteLine("List selected value: " + lstSupport.SelectedValue);
    }

    private void btnContactUs_Click(object sender, EventArgs e)
    {
    Debug.WriteLine("Contact Us post back button clicked.");
    Debug.WriteLine("List selected value: " + lstContactUs.SelectedValue);
    }
    }
    }

    ************************************************************
     
    Eric D. Wilson, Jun 30, 2005
    #1
    1. Advertising

  2. I guess I should have included a little explanation of the demo.

    If you're familiar with the tabstrip.aspx demo that's included with the IE
    web controls distribution you probably already know that the page just shows
    5 tabs (Home, About Us, Products, Support, and Contact Us).

    In my altered demo I've added a listbox to each page and a button that
    initiates a post back.

    During the Page_Load() event I programmatically remove the 'Products' tab.
    Now when you click on an item in either the list box on either the 'Support'
    or 'Contact Us' tabs and then click the 'Post Back' button what you should
    see in the debug output is a printout of the value of the selected item in
    the listbox. However, that won't happen because the view state for the
    listbox has been lost. If you check the SelectedIndex property it will show
    '-1'.

    Eric

    "Eric D. Wilson" wrote:

    > I thought I'd post some info about a bug I've found in the way viewstate is
    > handled (or not handled for that matter) when you dynamically remove a tab
    > from the IE Web Control TabStrip control.
    >
    > I've got a web app that uses the tabstrip to partition various types of data
    > with each tab corrosponding to a "feature". On each tab are several server
    > controls including ListBoxes. Part of the business logic is that a user can
    > select an item in a listbox and then click a button to initiate a post back.
    > On the server I'd check to see what the select index value was and then
    > provide a pop-up with details specific to the selected item (the pop-up is
    > created using the RegisterClientScriptBlock() and a JavaScript function
    > included in the page definition).
    >
    > When the page initially loads I check to see what features are
    > enabled/disabled based on a setting in a database. When a feature is disabled
    > I remove the tab that corrosponds to the feature from the tabstrip in the
    > Page_Load() event. This only has to be done when IsPostBack is false as the
    > viewstate will be maintained properly for the tabstrip itself.
    >
    > This is where the funny part starts.
    >
    > If there are ASP.NET ListBox controls on any of the subsequent tabs, their
    > viewstate will be lost when a preceding tab is removed. I haven't tested
    > every server control yet, but so far this behavior only appears to effect
    > ListBox controls.
    >
    > I haven't taken the time to look through the code for the TabStrip,
    > MultiPage, or PageView yet as I was able to come up with a work around.
    >
    > To work around the problem you can simply set the Enabled property of the
    > disabled tab(s) to false. The tab will still be rendered but you won't be
    > able to activate it.
    >
    > I've put together a demo of behavior using the tabstrip example that came
    > with the IE web controls distribution. It's a little contrived but it shows
    > the problem.
    >
    > Here's the source for my doctored "tabstrip.aspx" page.
    >
    > ************************************************************
    > <%@ Register TagPrefix="iewc" Namespace="Microsoft.Web.UI.WebControls"
    > Assembly="Microsoft.Web.UI.WebControls" %>
    > <%@ Page language="c#" Codebehind="tabstrip.aspx.cs" AutoEventWireup="false"
    > enableViewState="True" Trace="false" Inherits="IEWebCtrlSamples.tabstrip" %>
    > <HTML>
    > <body>
    > <form runat="server">
    > <iewc:TabStrip ID="tsTest" runat="server"
    > TabDefaultStyle="background-color:#000000;font-family:verdana;font-weight:bold;font-size:8pt;color:#ffffff;width:79;height:21;text-align:center"
    > TabHoverStyle="background-color:#777777"
    > TabSelectedStyle="background-color:#ffffff;color:#000000"
    > TargetID="mpTest">
    > <iewc:Tab ID="tabHome" Text="Home" />
    > <iewc:Tab ID="tabAboutUs" Text="About us" />
    > <iewc:Tab ID="tabProducts" Text="Products" />
    > <iewc:Tab ID="tabSupport" Text="Support" />
    > <iewc:Tab ID="tabContactUs" Text="Contact us" />
    > </iewc:TabStrip>
    > <iewc:MultiPage id="mpTest" runat="server" Height="100%">
    > <iewc:pageView id="pvHome">
    > <asp:panel ID="panHome" Runat="server">
    > <br />
    > Home
    > <br />
    > <asp:ListBox ID="lstHome" Runat="server" Width="300px" Rows="10"
    > EnableViewState="True"></asp:ListBox>
    > <br />
    > <asp:button id="btnHome" runat="server" Text="Post Back"></asp:button>
    > </asp:panel>
    > </iewc:pageView>
    > <iewc:pageView id="pvAboutUs">
    > <asp:panel ID="panAboutUs" Runat="server">
    > <br />
    > About Us
    > <br />
    > <asp:ListBox ID="lstAboutUs" Runat="server" Width="300px" Rows="10"
    > EnableViewState="True"></asp:ListBox>
    > <br />
    > <asp:button id="btnAboutUs" runat="server" Text="Post
    > Back"></asp:button>
    > </asp:panel>
    > </iewc:pageView>
    > <iewc:pageView id="pvProducts">
    > <asp:panel ID="panProducts" Runat="server">
    > <br />
    > Products
    > <br />
    > <asp:ListBox ID="lstProducts" Runat="server" Width="300px" Rows="10"
    > EnableViewState="True"></asp:ListBox>
    > <br />
    > <asp:button id="btnProducts" runat="server" Text="Post
    > Back"></asp:button>
    > </asp:panel>
    > </iewc:pageView>
    > <iewc:pageView id="pvSupport">
    > <asp:panel ID="panSupport" Runat="server">
    > <br />
    > Support
    > <br />
    > <asp:ListBox ID="lstSupport" Runat="server" Width="300px" Rows="10"
    > EnableViewState="True"></asp:ListBox>
    > <br />
    > <asp:button id="btnSupport" runat="server" Text="Post
    > Back"></asp:button>
    > </asp:panel>
    > </iewc:pageView>
    > <iewc:pageView id="pvContactUs">
    > <asp:panel ID="panContactUs" Runat="server">
    > <br />
    > Contact Us
    > <br />
    > <asp:ListBox ID="lstContactUs" Runat="server" Width="300px" Rows="10"
    > EnableViewState="True"></asp:ListBox>
    > <br />
    > <asp:button id="btnContactUs" runat="server" Text="Post
    > Back"></asp:button>
    > </asp:panel>
    > </iewc:pageView>
    > </iewc:MultiPage>
    > </form>
    > </body>
    > </HTML>
    >
    > ************************************************************
    >
    > Here's the source for the codebehind page that removes a tab.
    >
    > ************************************************************
    >
    > using System;
    > using System.Collections;
    > using System.ComponentModel;
    > using System.Data;
    > using System.Drawing;
    > using System.Diagnostics;
    > using System.Web;
    > using System.Web.SessionState;
    > using System.Web.UI;
    > using System.Web.UI.WebControls;
    > using System.Web.UI.HtmlControls;
    >
    > namespace IEWebCtrlSamples
    > {
    > /// <summary>
    > /// Summary description for WebForm1.
    > /// </summary>
    > public class tabstrip : System.Web.UI.Page
    > {
    > protected Microsoft.Web.UI.WebControls.TabStrip tsTest;
    > protected Microsoft.Web.UI.WebControls.MultiPage mpTest;
    >
    > protected Microsoft.Web.UI.WebControls.Tab tabHome;
    > protected Microsoft.Web.UI.WebControls.PageView pvHome;
    > protected System.Web.UI.WebControls.Panel panHome;
    > protected System.Web.UI.WebControls.ListBox lstHome;
    > protected System.Web.UI.WebControls.Button btnHome;
    >
    > protected Microsoft.Web.UI.WebControls.Tab tabAboutUs;
    > protected Microsoft.Web.UI.WebControls.PageView pvAboutUs;
    > protected System.Web.UI.WebControls.Panel panAboutUs;
    > protected System.Web.UI.WebControls.ListBox lstAboutUs;
    > protected System.Web.UI.WebControls.Button btnAboutUs;
    >
    > protected Microsoft.Web.UI.WebControls.Tab tabProducts;
    > protected Microsoft.Web.UI.WebControls.PageView pvProducts;
    > protected System.Web.UI.WebControls.Panel panProducts;
    > protected System.Web.UI.WebControls.ListBox lstProducts;
    > protected System.Web.UI.WebControls.Button btnProducts;
    >
    > protected Microsoft.Web.UI.WebControls.Tab tabSupport;
    > protected Microsoft.Web.UI.WebControls.PageView pvSupport;
    > protected System.Web.UI.WebControls.Panel panSupport;
    > protected System.Web.UI.WebControls.ListBox lstSupport;
    > protected System.Web.UI.WebControls.Button btnSupport;
    >
    > protected Microsoft.Web.UI.WebControls.Tab tabContactUs;
    > protected Microsoft.Web.UI.WebControls.PageView pvContactUs;
    > protected System.Web.UI.WebControls.Panel panContactUs;
    > protected System.Web.UI.WebControls.ListBox lstContactUs;
    > protected System.Web.UI.WebControls.Button btnContactUs;
    >
    > private void Page_Load(object sender, System.EventArgs e)
    > {
    > if (!IsPostBack)
    > {
    > tsTest.Items.Remove(tabProducts);
    >
    > lstHome.Items.Add("Home 1");
    > lstHome.Items.Add("Home 2");
    >
    > lstAboutUs.Items.Add("About Us 1");
    > lstAboutUs.Items.Add("About Us 2");
    >
    > lstProducts.Items.Add("Products 1");
    > lstProducts.Items.Add("Products 2");
    >
    > lstSupport.Items.Add("Support 1");
    > lstSupport.Items.Add("Support 2");
    >
    > lstContactUs.Items.Add("Contact Us 1");
    > lstContactUs.Items.Add("Contact Us 2");
    >
    > }
    >
    > panProducts.Visible = false;
    > mpTest.Controls.Remove(pvProducts);
    >
    > // Put user code to initialize the page here
    > Debug.WriteLine("Tab strip selected index: " + tsTest.SelectedIndex);
    > }
    >
    >
    > #region Web Form Designer generated code
    > override protected void OnInit(EventArgs e)
    > {
    > //
    > // CODEGEN: This call is required by the ASP.NET Web Form Designer.
    > //
    > InitializeComponent();
    > base.OnInit(e);
    > }
    >
    > /// <summary>
    > /// Required method for Designer support - do not modify
    > /// the contents of this method with the code editor.
    > /// </summary>
    > private void InitializeComponent()
    > {
    > this.Load += new System.EventHandler(this.Page_Load);
    >
    > this.btnHome.Click += new EventHandler(btnHome_Click);
    > this.btnAboutUs.Click += new EventHandler(btnAboutUs_Click);
    > this.btnProducts.Click += new EventHandler(btnProducts_Click);
    > this.btnSupport.Click += new EventHandler(btnSupport_Click);
    > this.btnContactUs.Click += new EventHandler(btnContactUs_Click);
    > }
    > #endregion
    >
    > private void btnHome_Click(object sender, EventArgs e)
    > {
    > Debug.WriteLine("Home post back button clicked.");
    > Debug.WriteLine("List selected value: " + lstHome.SelectedValue);
    > }
    >
    > private void btnAboutUs_Click(object sender, EventArgs e)
    > {
    > Debug.WriteLine("About Us post back button clicked.");
    > Debug.WriteLine("List selected value: " + lstAboutUs.SelectedValue);
    > }
    >
    > private void btnProducts_Click(object sender, EventArgs e)
    > {
    > Debug.WriteLine("Products post back button clicked.");
    > Debug.WriteLine("List selected value: " + lstProducts.SelectedValue);
    > }
    >
    > private void btnSupport_Click(object sender, EventArgs e)
    > {
    > Debug.WriteLine("Support post back button clicked.");
    > Debug.WriteLine("List selected value: " + lstSupport.SelectedValue);
    > }
    >
    > private void btnContactUs_Click(object sender, EventArgs e)
    > {
    > Debug.WriteLine("Contact Us post back button clicked.");
    > Debug.WriteLine("List selected value: " + lstContactUs.SelectedValue);
    > }
    > }
    > }
    >
    > ************************************************************
     
    Eric D. Wilson, Jun 30, 2005
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gordon Moore
    Replies:
    0
    Views:
    448
    Gordon Moore
    Jun 27, 2003
  2. Gvnn
    Replies:
    2
    Views:
    1,252
    Saravana [MVP]
    Oct 18, 2003
  3. Ben Rush
    Replies:
    2
    Views:
    556
    Ben Rush
    Dec 5, 2003
  4. Nicolas LeBlanc
    Replies:
    2
    Views:
    2,571
    Nicolas LeBlanc
    Feb 19, 2004
  5. =?Utf-8?B?TWFnZGVsaW4=?=

    ViewState Corrupted in Web Farm

    =?Utf-8?B?TWFnZGVsaW4=?=, Dec 6, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    2,421
    =?Utf-8?B?TWFnZGVsaW4=?=
    Dec 6, 2004
Loading...

Share This Page