Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 616
  • Last Modified:

Maintain State Using LoadControl()

Hi,

I'm new to using templated controls and I'm developing an in-house Asp.Net application to provide "maintenance" type tools for our developers.  I have made each tool a User Control.  On the main page, I have a menu (made up of link buttons) listing each tool.  When the user clicks on a button to select a tool, I am using the LoadControl() method to load the User Control into the content area (a panel server control).  The control loads fine, but the problem is, the User Control has multiple buttons, pageable datagrids, etc. to perform their tasks.  When anything in the User Control causes a postback, the entire control disappears.  The panel control EnableViewState property is set to true.  Any ideas?  Here is a generic portion of some of the code:

Menu.aspx:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="Menu.aspx.vb" Inherits="AdminTools.Menu"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
      <HEAD>
            <title>Programmer's Admin Tools</title>
            <meta content="Microsoft Visual Studio.NET 7.0" name="GENERATOR">
            <meta content="Visual Basic 7.0" name="CODE_LANGUAGE">
            <meta content="JavaScript" name="vs_defaultClientScript">
            <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
            <LINK href="Styles.css" type="text/css" rel="stylesheet">
      </HEAD>
      <body>
            <form id="Form1" method="post" runat="server">
                  <TABLE id="Table1" cellSpacing="1" cellPadding="1" border="0">
                        <TR>
                              <TD vAlign="bottom" noWrap>
                                    <H2>Programmer's Admin Tools</H2>
                              </TD>
                        </TR>
                        <TR>
                              <TD>
                                    <TABLE id="Table2" cellSpacing="1" cellPadding="1" width="100%" border="0">
                                          <TR>
                                                <TD vAlign="top" width="190">
                                                      <H5>MENU</H5>
                                                      <P><asp:linkbutton id="cmdSetSystemSecurity" runat="server">Set Security for Internal System</asp:linkbutton><br>
                                                            <asp:LinkButton id="cmdPersonManagement" runat="server">Manage Person Master Database</asp:LinkButton></P>
                                                </TD>
                                                <TD vAlign="top" width="10"></TD>
                                                <TD vAlign="top">
                                                      <asp:Panel id="pnlControlHolder" runat="server"></asp:Panel></TD>
                                          </TR>
                                    </TABLE>
                              </TD>
                        </TR>
                  </TABLE>
            </form>
      </body>
</HTML>

Menu.aspx.vb:

Public Class Menu
    Inherits System.Web.UI.Page
    Protected WithEvents cmdSetSystemSecurity As System.Web.UI.WebControls.LinkButton
    Protected WithEvents pnlControlHolder As System.Web.UI.WebControls.Panel
    Protected WithEvents cmdPersonManagement As System.Web.UI.WebControls.LinkButton

#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
    End Sub

    Private Sub cmdSetSystemSecurity_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSetSystemSecurity.Click
        Dim mySecurityControl As SetSecurityForSystem = LoadControl("SetSecurityForSystem.ascx")
        pnlControlHolder.Controls.Add(mySecurityControl)
    End Sub
End Class

SetSecurityForSystem.ascx:

<%@ Control Language="vb" AutoEventWireup="false" Codebehind="SetSecurityForSystem.ascx.vb" Inherits="AdminTools.SetSecurityForSystem" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<TABLE id="Table1" cellSpacing="1" cellPadding="1" border="0">
      <TR>
            <TD vAlign="top" align="right">System Name:</TD>
            <TD>
                  <asp:TextBox id="txtSystemName" runat="server" MaxLength="50" Columns="30"></asp:TextBox></TD>
      </TR>
      <TR>
            <TD vAlign="top" align="right">Authorized Users:</TD>
            <TD>
                  <asp:ListBox id="lstUsers" runat="server" Rows="20" SelectionMode="Multiple"></asp:ListBox></TD>
      </TR>
      <TR>
            <TD></TD>
            <TD>
                  <asp:Button id="cmdSetSecurity" runat="server" Text="Set Security"></asp:Button></TD>
      </TR>
      <TR>
            <TD></TD>
            <TD></TD>
      </TR>
</TABLE>

SetSecurityForSystem.ascx.vb:

Imports Microsoft.ApplicationBlocks.Data

Public MustInherit Class SetSecurityForSystem
    Inherits System.Web.UI.UserControl
    Protected WithEvents txtSystemName As System.Web.UI.WebControls.TextBox
    Protected WithEvents lstUsers As System.Web.UI.WebControls.ListBox
    Protected WithEvents cmdSetSecurity As System.Web.UI.WebControls.Button

#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
        lstUsers.DataSource = SqlHelper.ExecuteReader(ConfigurationSettings.AppSettings("ConnectionString"), CommandType.Text, "SELECT personid, RTRIM(username) + ' (' + RTRIM(userid_short) + ')' As Name FROM companyperson")
        lstUsers.DataTextField = "Name"
        lstUsers.DataValueField = "personid"
        lstUsers.DataBind()
    End Sub

End Class

Thanks in advance for the help.
0
DJDoug
Asked:
DJDoug
1 Solution
 
reavesCommented:
When you are creating dynamic controls in a container, you have to recreate each control with every postback. It seems weird, I know, because after you recreate the dynamic control it's propertires and values will still be restored by viewstate. You just have to alert your page that these controls still exist since you are not doing it declaratively.

So:

Add this Property:

'This property will keep track of how many control we have on the page
Private Property ControlCount() As Integer
  Set(ByVal Value As Integer)
    ViewState("ControlCount") = Value
  End Set
  Get
    If ViewState("ControlCount") Is Nothing Then
      ViewState("ControlCount") = 0
    End If
    Return ViewState("ControlCount")
  End Get
End Property


Add this sub:

'This sub will call laodcontrol and add the control to the page
Private Sub CreateControl(ByVal intIndex As Integer)
  Dim mySecurityControl As SetSecurityForSystem = LoadControl("SetSecurityForSystem.ascx")
  pnlControlHolder.Controls.Add(mySecurityControl)
  mySecurityControl.ID = "mySecurityControl" & intIndex
End Sub


Change your click event handler to this:

   'Add a new control and increment our counter when the button is clicked
   Private Sub cmdSetSystemSecurity_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSetSystemSecurity.Click
     CreateControl(ControlCount)
     ControlCount += 1
   End Sub

Change your Page_Load to this:

   'If the page is posted back, check our counter and re add teh appropriate number of controls
   Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      Dim intIndex As Integer = 0
      If Page.IsPostback()
        For intIndex = 0 To ControlCount - 1
          CreateControl(intIndex)
        Next
      End If
   End Sub



So if you filter that for typos :) and re add the dynamic controls each time the page posts back, then you will they will reappear WITH their pre postback properties.

--
Ryan Eaves
0
 
DJDougAuthor Commented:
Works like a charm (with no typos... :) !).  Thanks for the superfast response...AWESOME!  Appreciate it.  Take care.
0

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now