Viewstate and Dynmac controls

Discussion in 'ASP .Net Web Controls' started by Steve Drake, Nov 20, 2003.

  1. Steve Drake

    Steve Drake Guest

    All,

    I have a CONTROL that contains 1 control (Control ONE), the 1 control that
    it can contain 1 or 2 control (Control A and B).

    Control A, raises and event and Control ONE receives this event and this
    causes control B to be created, when this is done the VIEWSTATE is lost for
    CONTROL B.

    In the EVENT that causes CONTROL B to be created I have to set
    ChildControlsCreated to false, if I don't set it the viewstate works but the
    control doesn't show, as the createchild controls does not get re-ran.

    Below is the a smaller version of the code that I have created to reproduce
    the problem test as follows :

    Click Get Current Time, it will now show the time
    Click do post back, it will still show time in first step, as well as time
    of post back, to prove its posted back.
    Click Raise Event, it has now lost the viewstate, time has gone blank.
    Click Get Current Time on both line, you will see the time get filled in and
    it persisted in the viewstate, do a few clicks to prove this.
    Now Click Raise Event, view state has been lost again.

    Cheers

    Steve

    Project name should be ViewStateTest

    Code : (Add to single class called controls.cs)

    using System;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    namespace ViewStateTest
    {
    public class ContainTime : WebControl ,INamingContainer
    {
    ShowTime showtimeA;
    ShowTime showtimeB;

    WebControl holdingcontrol;

    bool showB;

    protected override void LoadViewState(object savedState)
    {

    base.LoadViewState (savedState);
    if (ViewState["ShowB"] == null)
    {
    showB = false;
    }
    else
    {
    showB = (bool) ViewState["ShowB"];
    }

    }
    protected override object SaveViewState()
    {
    ViewState["ShowB"] = showB;
    return base.SaveViewState ();
    }

    protected override void CreateChildControls()
    {
    Controls.Clear();
    showtimeA = new ShowTime();
    showtimeA.Click+=new EventHandler(showtimeA_Click);
    Controls.Add(showtimeA);

    if (showB )
    {
    showtimeB = new ShowTime();
    Controls.Add(showtimeB);
    }
    }
    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
    showtimeA.RenderControl(writer);
    if (showB) showtimeB.RenderControl(writer);
    }

    public ContainTime()
    {

    }

    private void showtimeA_Click(object sender, EventArgs e)
    {
    this.showB = !showB;
    this.ChildControlsCreated = false; // if I dont do this, the control is
    there
    // its the above line that makes the viewstate vanish, but I need it to
    cause the controls to dynamicly add.
    }
    }

    /// <summary>
    /// Summary description for ShowTime.
    /// </summary>
    public class ShowTime : WebControl,INamingContainer
    {
    public ShowTime()
    {
    }

    string timestring;
    Button abutton;
    Button getTimeButton;
    Button doRoundTrip;

    Label timelabel;

    public event EventHandler Click;

    protected override void LoadViewState(object savedState)
    {
    base.LoadViewState (savedState);
    System.Diagnostics.Trace.WriteLine("Items in viewstate " +
    ViewState.Count);

    if (ViewState["time"] == null)
    {
    timestring = "Not found";
    }
    else
    {
    timestring = (string) ViewState["time"];
    }
    }
    protected override object SaveViewState()
    {
    ViewState["time"] = timestring;
    return base.SaveViewState ();
    }

    protected override void CreateChildControls()
    {
    // For this example we could just write the time out in the render, but I
    need to mimic the class
    // that I am having problems with as much as possable.
    Controls.Clear();
    timelabel = new Label();
    timelabel.Text = timestring;
    abutton = new Button();
    abutton.Text = "Raise Event";
    abutton.Click+=new System.EventHandler(abutton_Click);

    getTimeButton = new Button();
    getTimeButton.Text = "Get Current Time";
    getTimeButton.Click+=new EventHandler(getTimeButton_Click);

    doRoundTrip = new Button();
    doRoundTrip.Text = "Do Post Back";
    doRoundTrip.Click+=new EventHandler(doRoundTrip_Click);

    Controls.Add(timelabel);
    Controls.Add(abutton);
    Controls.Add(getTimeButton);
    Controls.Add(doRoundTrip);
    }
    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
    writer.RenderBeginTag("DIV");
    writer.Write(this.UniqueID);
    EnsureChildControls();
    timelabel.RenderControl(writer);
    abutton.RenderControl(writer);
    getTimeButton.RenderControl(writer);
    writer.Write("Time of post back " + System.DateTime.Now.ToString());
    doRoundTrip.RenderControl(writer);
    writer.RenderEndTag();
    }

    private void abutton_Click(object sender, System.EventArgs e)
    {
    Click(this,e);
    }

    private void getTimeButton_Click(object sender, EventArgs e)
    {
    this.timestring = System.DateTime.Now.ToString();
    ChildControlsCreated=false;
    }

    private void doRoundTrip_Click(object sender, EventArgs e)
    {
    System.Diagnostics.Trace.WriteLine("Round trip");
    ChildControlsCreated=false;
    }
    }
    }


    CODE BEHIND CODE

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

    namespace ViewStateTest
    {
    /// <summary>
    /// Summary description for WebForm1.
    /// </summary>
    public class WebForm1 : System.Web.UI.Page
    {
    protected ViewStateTest.ContainTime ContainTime1;

    private void Page_Load(object sender, System.EventArgs e)
    {
    // Put user code to initialize the page here
    }

    #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);

    }
    #endregion
    }
    }


    ASPX PAGE :


    <%@ Register TagPrefix="cc1" Namespace="ViewStateTest"
    Assembly="ViewStateTest" %>
    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
    Inherits="ViewStateTest.WebForm1" smartNavigation="True"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
    <HEAD>
    <title>WebForm1</title>
    <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
    <meta name="CODE_LANGUAGE" Content="C#">
    <meta name="vs_defaultClientScript" content="JavaScript">
    <meta name="vs_targetSchema"
    content="http://schemas.microsoft.com/intellisense/ie5">
    </HEAD>
    <body MS_POSITIONING="GridLayout">
    <form id="Form1" method="post" runat="server">
    <cc1:ContainTime id="ContainTime1" style="Z-INDEX: 101; LEFT: 56px;
    POSITION: absolute; TOP: 48px"
    runat="server"></cc1:ContainTime>
    </form>
    </body>
    </HTML>
    Steve Drake, Nov 20, 2003
    #1
    1. Advertising

  2. Steve Drake

    Steve Drake Guest

    I fixed this as follows (note new BASE CLASS), comments welcome:

    using System;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    namespace ViewStateTest
    {
    public class myControl : WebControl
    {
    internal object mySaveViewState()
    {
    return this.SaveViewState ();
    }
    internal void myLoadViewState(object savedState)
    {
    this.LoadViewState (savedState);
    }
    internal void myTrackViewState()
    {
    this.TrackViewState();
    }
    }

    public class ContainTime : myControl,INamingContainer
    {

    showtime showtimeA=new showtime();
    showtime showtimeB=new showtime();



    System.Web.UI.WebControls.Calendar calA;
    System.Web.UI.WebControls.Calendar calB;

    WebControl holdingcontrol;

    bool showB;



    protected override void LoadViewState(object savedState)
    {
    if (savedState!=null)
    {
    object[] states = (object[]) savedState;

    if(states[0] != null)
    base.LoadViewState(states[0]);
    if(states[1] != null)
    showtimeA.myLoadViewState(states[1]);
    if(states[2] != null)
    showtimeB.myLoadViewState(states[2]);


    }

    /* Load Custom View State here */
    object o = ViewState["ShowB"] ;
    if (o== null)
    showB = false;
    else
    showB = (bool) o;

    }
    protected override object SaveViewState()
    {

    ViewState["ShowB"] = showB;

    object[] states = new object [3];
    states[0] = base.SaveViewState();
    states[1] = (showtimeA== null ? null : showtimeA.mySaveViewState());
    states[2] = (showtimeB== null ? null : showtimeB.mySaveViewState());
    for(int i=0; i < states.Length; i++)
    {
    if(states!=null)
    return states;
    }
    return null;
    }
    protected override void CreateChildControls()
    {
    Controls.Clear();
    showtimeA.ID = "SA";
    showtimeB.ID = "SB";

    showtimeA.Click+=new EventHandler(showtimeA_Click);
    Controls.Add(showtimeA);
    calA = new Calendar();
    Controls.Add(calA);

    // if (showB )
    {
    calB = new Calendar();
    Controls.Add(showtimeB);
    Controls.Add(calB);
    }
    }
    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
    showtimeA.RenderControl(writer);
    calA.RenderControl(writer);
    if (showB) showtimeB.RenderControl(writer);
    if (showB) calB.RenderControl(writer);
    }


    protected override void TrackViewState()
    {
    base.TrackViewState ();
    }

    public ContainTime()
    {
    showtimeA=new showtime();
    showtimeB=new showtime();

    }

    private void showtimeA_Click(object sender, EventArgs e)
    {
    this.showB = !showB;
    this.ChildControlsCreated = false;
    }
    }

    /// <summary>
    /// Summary description for showtime.
    /// </summary>
    public class showtime : myControl,INamingContainer
    {
    public showtime()
    {
    }

    string timestring;
    Button abutton;
    Button getTimeButton;
    Button doRoundTrip;

    Label timelabel;

    public event EventHandler Click;

    protected override void LoadViewState(object savedState)
    {
    base.LoadViewState (savedState);
    System.Diagnostics.Trace.WriteLine("Items in viewstate " +
    ViewState.Count);

    if (ViewState["time"] == null)
    {
    timestring = "Not found";
    }
    else
    {
    timestring = (string) ViewState["time"];
    }
    }
    protected override object SaveViewState()
    {
    ViewState["time"] = timestring;
    return base.SaveViewState ();
    }

    protected override void CreateChildControls()
    {
    // For this example we could just write the time out in the render, but I
    need to mimic the class
    // that I am having problems with as much as possable.
    Controls.Clear();
    timelabel = new Label();
    timelabel.Text = timestring;
    abutton = new Button();
    abutton.Text = "Raise Event";
    abutton.Click+=new System.EventHandler(abutton_Click);

    getTimeButton = new Button();
    getTimeButton.Text = "Get Current Time";
    getTimeButton.Click+=new EventHandler(getTimeButton_Click);

    doRoundTrip = new Button();
    doRoundTrip.Text = "Do Post Back";
    doRoundTrip.Click+=new EventHandler(doRoundTrip_Click);

    Controls.Add(timelabel);
    Controls.Add(abutton);
    Controls.Add(getTimeButton);
    Controls.Add(doRoundTrip);
    }
    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
    writer.RenderBeginTag("DIV");
    writer.Write(this.UniqueID);
    EnsureChildControls();
    timelabel.RenderControl(writer);
    abutton.RenderControl(writer);
    getTimeButton.RenderControl(writer);
    writer.Write("Time of post back " + System.DateTime.Now.ToString());
    doRoundTrip.RenderControl(writer);
    writer.RenderEndTag();
    }

    private void abutton_Click(object sender, System.EventArgs e)
    {
    base.TrackViewState ();

    Click(this,e);
    }

    private void getTimeButton_Click(object sender, EventArgs e)
    {
    this.timestring = System.DateTime.Now.ToString();
    ChildControlsCreated=false;
    }

    private void doRoundTrip_Click(object sender, EventArgs e)
    {
    System.Diagnostics.Trace.WriteLine("Round trip");
    ChildControlsCreated=false;
    }
    }
    }

    "Steve Drake" <Steve@_NOSPAM_Drakey.co.uk> wrote in message
    news:...
    > All,
    >
    > I have a CONTROL that contains 1 control (Control ONE), the 1 control that
    > it can contain 1 or 2 control (Control A and B).
    >
    > Control A, raises and event and Control ONE receives this event and this
    > causes control B to be created, when this is done the VIEWSTATE is lost

    for
    > CONTROL B.
    >
    > In the EVENT that causes CONTROL B to be created I have to set
    > ChildControlsCreated to false, if I don't set it the viewstate works but

    the
    > control doesn't show, as the createchild controls does not get re-ran.
    >
    > Below is the a smaller version of the code that I have created to

    reproduce
    > the problem test as follows :
    >
    > Click Get Current Time, it will now show the time
    > Click do post back, it will still show time in first step, as well as time
    > of post back, to prove its posted back.
    > Click Raise Event, it has now lost the viewstate, time has gone blank.
    > Click Get Current Time on both line, you will see the time get filled in

    and
    > it persisted in the viewstate, do a few clicks to prove this.
    > Now Click Raise Event, view state has been lost again.
    >
    > Cheers
    >
    > Steve
    >
    > Project name should be ViewStateTest
    >
    > Code : (Add to single class called controls.cs)
    >
    > using System;
    > using System.Web;
    > using System.Web.UI;
    > using System.Web.UI.WebControls;
    >
    > namespace ViewStateTest
    > {
    > public class ContainTime : WebControl ,INamingContainer
    > {
    > ShowTime showtimeA;
    > ShowTime showtimeB;
    >
    > WebControl holdingcontrol;
    >
    > bool showB;
    >
    > protected override void LoadViewState(object savedState)
    > {
    >
    > base.LoadViewState (savedState);
    > if (ViewState["ShowB"] == null)
    > {
    > showB = false;
    > }
    > else
    > {
    > showB = (bool) ViewState["ShowB"];
    > }
    >
    > }
    > protected override object SaveViewState()
    > {
    > ViewState["ShowB"] = showB;
    > return base.SaveViewState ();
    > }
    >
    > protected override void CreateChildControls()
    > {
    > Controls.Clear();
    > showtimeA = new ShowTime();
    > showtimeA.Click+=new EventHandler(showtimeA_Click);
    > Controls.Add(showtimeA);
    >
    > if (showB )
    > {
    > showtimeB = new ShowTime();
    > Controls.Add(showtimeB);
    > }
    > }
    > protected override void Render(System.Web.UI.HtmlTextWriter writer)
    > {
    > showtimeA.RenderControl(writer);
    > if (showB) showtimeB.RenderControl(writer);
    > }
    >
    > public ContainTime()
    > {
    >
    > }
    >
    > private void showtimeA_Click(object sender, EventArgs e)
    > {
    > this.showB = !showB;
    > this.ChildControlsCreated = false; // if I dont do this, the control is
    > there
    > // its the above line that makes the viewstate vanish, but I need it to
    > cause the controls to dynamicly add.
    > }
    > }
    >
    > /// <summary>
    > /// Summary description for ShowTime.
    > /// </summary>
    > public class ShowTime : WebControl,INamingContainer
    > {
    > public ShowTime()
    > {
    > }
    >
    > string timestring;
    > Button abutton;
    > Button getTimeButton;
    > Button doRoundTrip;
    >
    > Label timelabel;
    >
    > public event EventHandler Click;
    >
    > protected override void LoadViewState(object savedState)
    > {
    > base.LoadViewState (savedState);
    > System.Diagnostics.Trace.WriteLine("Items in viewstate " +
    > ViewState.Count);
    >
    > if (ViewState["time"] == null)
    > {
    > timestring = "Not found";
    > }
    > else
    > {
    > timestring = (string) ViewState["time"];
    > }
    > }
    > protected override object SaveViewState()
    > {
    > ViewState["time"] = timestring;
    > return base.SaveViewState ();
    > }
    >
    > protected override void CreateChildControls()
    > {
    > // For this example we could just write the time out in the render, but

    I
    > need to mimic the class
    > // that I am having problems with as much as possable.
    > Controls.Clear();
    > timelabel = new Label();
    > timelabel.Text = timestring;
    > abutton = new Button();
    > abutton.Text = "Raise Event";
    > abutton.Click+=new System.EventHandler(abutton_Click);
    >
    > getTimeButton = new Button();
    > getTimeButton.Text = "Get Current Time";
    > getTimeButton.Click+=new EventHandler(getTimeButton_Click);
    >
    > doRoundTrip = new Button();
    > doRoundTrip.Text = "Do Post Back";
    > doRoundTrip.Click+=new EventHandler(doRoundTrip_Click);
    >
    > Controls.Add(timelabel);
    > Controls.Add(abutton);
    > Controls.Add(getTimeButton);
    > Controls.Add(doRoundTrip);
    > }
    > protected override void Render(System.Web.UI.HtmlTextWriter writer)
    > {
    > writer.RenderBeginTag("DIV");
    > writer.Write(this.UniqueID);
    > EnsureChildControls();
    > timelabel.RenderControl(writer);
    > abutton.RenderControl(writer);
    > getTimeButton.RenderControl(writer);
    > writer.Write("Time of post back " + System.DateTime.Now.ToString());
    > doRoundTrip.RenderControl(writer);
    > writer.RenderEndTag();
    > }
    >
    > private void abutton_Click(object sender, System.EventArgs e)
    > {
    > Click(this,e);
    > }
    >
    > private void getTimeButton_Click(object sender, EventArgs e)
    > {
    > this.timestring = System.DateTime.Now.ToString();
    > ChildControlsCreated=false;
    > }
    >
    > private void doRoundTrip_Click(object sender, EventArgs e)
    > {
    > System.Diagnostics.Trace.WriteLine("Round trip");
    > ChildControlsCreated=false;
    > }
    > }
    > }
    >
    >
    > CODE BEHIND CODE
    >
    > using System;
    > using System.Collections;
    > using System.ComponentModel;
    > using System.Data;
    > using System.Drawing;
    > using System.Web;
    > using System.Web.SessionState;
    > using System.Web.UI;
    > using System.Web.UI.WebControls;
    > using System.Web.UI.HtmlControls;
    >
    > namespace ViewStateTest
    > {
    > /// <summary>
    > /// Summary description for WebForm1.
    > /// </summary>
    > public class WebForm1 : System.Web.UI.Page
    > {
    > protected ViewStateTest.ContainTime ContainTime1;
    >
    > private void Page_Load(object sender, System.EventArgs e)
    > {
    > // Put user code to initialize the page here
    > }
    >
    > #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);
    >
    > }
    > #endregion
    > }
    > }
    >
    >
    > ASPX PAGE :
    >
    >
    > <%@ Register TagPrefix="cc1" Namespace="ViewStateTest"
    > Assembly="ViewStateTest" %>
    > <%@ Page language="c#" Codebehind="WebForm1.aspx.cs"

    AutoEventWireup="false"
    > Inherits="ViewStateTest.WebForm1" smartNavigation="True"%>
    > <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    > <HTML>
    > <HEAD>
    > <title>WebForm1</title>
    > <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
    > <meta name="CODE_LANGUAGE" Content="C#">
    > <meta name="vs_defaultClientScript" content="JavaScript">
    > <meta name="vs_targetSchema"
    > content="http://schemas.microsoft.com/intellisense/ie5">
    > </HEAD>
    > <body MS_POSITIONING="GridLayout">
    > <form id="Form1" method="post" runat="server">
    > <cc1:ContainTime id="ContainTime1" style="Z-INDEX: 101; LEFT: 56px;
    > POSITION: absolute; TOP: 48px"
    > runat="server"></cc1:ContainTime>
    > </form>
    > </body>
    > </HTML>
    >
    >
    >
    >
    >
    >
    >
    Steve Drake, Nov 25, 2003
    #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. Steve Drake

    Viewstate and Dynmac controls

    Steve Drake, Nov 20, 2003, in forum: ASP .Net
    Replies:
    3
    Views:
    464
    Steve Drake
    Nov 25, 2003
  2. Ben Rush
    Replies:
    2
    Views:
    507
    Ben Rush
    Dec 5, 2003
  3. Steph
    Replies:
    2
    Views:
    1,647
    heislord5
    May 11, 2011
  4. ujjc001
    Replies:
    0
    Views:
    1,363
    ujjc001
    Jul 27, 2005
  5. sck10
    Replies:
    6
    Views:
    902
    sck10
    Sep 1, 2006
Loading...

Share This Page