ViewState of Child Controls Not Working Mystery???

E

Earl Teigrob

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
 
R

Robert Koritnik

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?
 
E

Earl Teigrob

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
 
Q

q

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

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top