ViewState of Child Controls Not Working Mystery???

Discussion in 'ASP .Net Web Controls' started by Earl Teigrob, Oct 7, 2004.

  1. Earl Teigrob

    Earl Teigrob Guest

    I can not get the child controls of my custom control to retain view state

    To use this control

    initial page load
    1. the containing page dynamically creates a control (button, in this case)
    and assigns it to the property "ControlToCreate".
    2. This property saves the type and id of the control in view state.
    3. The CreateChildControls Method Adds the control to its control collection
    4. The Button is Rendered to the Display

    on Postback
    1. The Containing page code to add the child control to the custom control
    is not run because it is in a Not IsPostback test.
    2. The CreateChildControls Method of the Custom Controls Calls the Property
    that holds the child control.;
    3. Becuase the child control field _ControlToRender is nothing, The Control
    is recreated with the Activator.CreateInstance method from the Type and the
    ID that where saved in ViewState.
    4. The control is added as a child control of the custom control
    5. The "Regenerated" control is rendered to the display BUT WITHOUT
    VIEWSTATE!!! All control viewstate settings are lost including the control
    text property

    The empty button is rendered to the display and in the trace, I can see the
    button in the control tree.

    Has someone solved this mystery???

    Thanks

    Earl


    CUSTOM CONTROL

    Imports System.ComponentModel
    Imports System.Web.UI

    <Serializable(), ToolboxData("<{0}:TabMenuA runat=server></{0}:TabMenuA>")>
    Public Class ContainerControl
    Inherits System.Web.UI.WebControls.WebControl

    #Region "Declarations"

    Private _ChildControlToRender As System.Web.UI.WebControls.WebControl

    #End Region

    #Region "Properties"

    <Bindable(True), Category("Data"), DefaultValue("")> Public Property
    ChildControlToRender() As System.Web.UI.WebControls.WebControl
    Get
    If Not _ChildControlToRender Is Nothing Then
    Return _ChildControlToRender
    Else
    _ChildControlToRender =
    Activator.CreateInstance(CType(ViewState("Type"), System.Type))
    _ChildControlToRender.ID = ViewState("ID")
    Return _ChildControlToRender
    End If
    End Get
    Set(ByVal Value As System.Web.UI.WebControls.WebControl)
    _ChildControlToRender = Value
    ViewState("Type") = Value.GetType
    ViewState("ID") = Value.ID
    End Set
    End Property

    #End Region

    #Region "Methods"

    Protected Overrides Sub CreateChildControls()
    Controls.Add(ChildControlToRender)
    End Sub

    #End Region


    End Class


    CONTAINING PAGE CODE BEHIND

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
    Dim myButton As Button = New Button
    myButton.Text = "Hello1"
    myButton.ID = "ButtonA"
    ContainerControl1.ChildControlToRender = myButton
    End If

    End Sub
     
    Earl Teigrob, Oct 7, 2004
    #1
    1. Advertisements

  2. Why don't you override the Save and load viewstate methods while you have to
    do everything based on viewstate values.

    I didn't exactly get the whole picture why and when you're doing something,
    but You should be aware of how exactly ViewState works. Create child
    controls happens before PageLoad, when view state is dispatched to controls,
    so things should be ok. As I have said. Maybe I didn't get the picture.

    Why don't you use Debug.WriteLine method calls to actually se what's going
    on in what order and writing information about your vital properties and
    method names that write the data to debug output window?
     
    Robert Koritnik, Oct 8, 2004
    #2
    1. Advertisements

  3. Earl Teigrob

    Earl Teigrob Guest

    Robert, Thanks for your response. I am doing some more research into this
    issue and have modified the code to be, what I believe, is closer to the
    solution. In the following code, I override the saveviewstate and
    loadviewstate methods (as you suggest) to create the regenerated controls
    before viewstate is run.

    Earl

    I am building a custom control that I want to server as a container for child
    controls that can be dynamically added to this control. I can persist the
    child controls that are added to my custom control but can to get them to
    retain view state.

    Below is a striped down version of my control. It exposes one property of
    type System.Web.UI.Control that the containing page my set with a dynamically
    created control My custom control will then add it to its control tree and
    render it to the display. The information need to recreate the control is
    stored in a System.Web.UI.Triplet object. On postback, the child control is
    reinstanced and given its origonal id and added to the Custom Controls
    control tree and rendered to the display.

    The only problem is that the ViewState for the child control is not being
    retained.

    Has anyone solved this puzzle???

    Thanks for your help

    Earl

    CUSTOM WEB SERVER CONTROL

    Imports System.ComponentModel
    Imports System.Web.UI

    <ToolboxData("<{0}:TabMenuA runat=server></{0}:TabMenuA>")> Public Class
    ContainerControl
    Inherits System.Web.UI.WebControls.WebControl

    #Region "Declarations"

    Private _ChildControlToRender As System.Web.UI.Control

    #End Region

    #Region "Properties"

    <Bindable(True), Category("Data"), DefaultValue("")> Public Property
    ChildControlToRender() As System.Web.UI.Control
    Get
    Return _ChildControlToRender
    End Get
    Set(ByVal Value As System.Web.UI.Control)
    _ChildControlToRender = Value
    End Set
    End Property

    #End Region

    #Region "Methods"

    Protected Overrides Sub CreateChildControls()
    If Not Page.IsPostBack Then
    Controls.Add(_ChildControlToRender)
    End If

    End Sub


    Protected Overrides Sub LoadViewState(ByVal savedState As Object)
    Dim objViewStates() As Object
    objViewStates = CType(savedState, Object())
    Dim Trip As System.Web.UI.Triplet
    Trip = objViewStates(1)
    _ChildControlToRender = Activator.CreateInstance(CType(Trip.Second,
    System.Type))
    _ChildControlToRender.ID = Trip.First
    Me.Controls.Add(_ChildControlToRender)
    MyBase.LoadViewState(objViewStates(0))
    End Sub

    Protected Overrides Function SaveViewState() As Object
    Dim objViewStates(1) As Object
    Dim Trip As New System.Web.UI.Triplet
    Trip.First = _ChildControlToRender.ID
    Trip.Second = _ChildControlToRender.GetType
    Trip.Third = Me.ID
    objViewStates(1) = Trip
    objViewStates(0) = MyBase.SaveViewState()
    Return objViewStates
    End Function

    #End Region
    End Class

    CONTAINING PAGE CODE

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
    Dim myButton As Button = New Button
    myButton.Text = "Hello1"
    myButton.ID = "ButtonA"
    myButton.EnableViewState = True
    ContainerControl1.ChildControlToRender = myButton
    End If

    End Sub
     
    Earl Teigrob, Oct 8, 2004
    #3
  4. Earl Teigrob

    q Guest

    The problem is in the following code:
    Protected Overrides Sub CreateChildControls()
    If Not Page.IsPostBack Then
    Controls.Add(_ChildControlToRender)
    End If

    End Sub

    change this to:
    Protected Overrides Sub CreateChildControls()
    Controls.Add(_ChildControlToRender)

    If Not Page.IsPostBack Then
    End If
    End Sub


    I had the same problem when programatically
    created DataGrid controls. Saw this solution somewhere.
    Do not recall exactly where though.
    BTW: I can have 0...N data grids created this way on a page.

    protected System.Web.UI.WebControls.PlaceHolder PlaceHolder1;
    private void Page_Load(object sender, System.EventArgs e)
    {
    InitDataGrid ();
    if (!IsPostBack)
    {
    }
    }
    protected void InitDataGrid ()
    {
    DataGrid gridData;
    gridData = new DataGrid();
    PlaceHolder1.Controls.Add(gridData);
    }
     
    q, Oct 9, 2004
    #4
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.