UpdatePanel with Dynamic Controls Inside and External to UpdatePanel

I have a ASPX page that reads data from a database, and creates a table dynamically, and adds it to an update panel. I also have other controls on the page that trigger the update panel data to update. My problem is that I can get the controls in the table (which is in the updatepanel) to work, or the controls outside of the update panel to work, butnot both at the same time.

I have cobbled together some code that recreates the problem.

Basically, I have a CheckBoxList ousdie of the UpdatePanel. When you check/uncheck a box, it displays/hides columns in the table  in the update panel. This only works when you comment out the doPostBackPageLoad() subroutine in Page_Load.

I also have ImageButtons at the top of each column in the table in the UpdatePanel to sort the table data ascending or descending. (Note that the sort function isn';t working here, but works in my original code). If I leave doPostBackPageLoad() commented out, the table disappears when I click on any of the sort buttons.

If I uncomment the doPostBackPageLoad() subroutine call, and refresh the page, the sort buttons work, but the CheckBoxList generates an error.

Any help would be greatly appreciated.

This is the aspx page (test_ppc_creative.aspx):

<%@ Page Language="VB" AutoEventWireup="true" CodeFile="test_ppc_creative.aspx.vb" Inherits="ppc_creative" %>

<%@ Register Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI" TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Untitled Page</title>
    <form id="form1" runat="server">
        <asp:CheckBoxList ID="frmCheckboxCurrentView" runat="server" AutoPostBack="True">
        </asp:CheckBoxList><br />
        <br />
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    <asp:UpdatePanel ID="UpdatePanelCreatives" runat="server" UpdateMode="Conditional">
                        <span class="heading_text"></span>
                        <table cellpadding="0" cellspacing="0" style="background: #cccccc; width: 100%">
                                <td style="width: 33%; height: 19px;" align="left">
                                <td style="width: 33%; height: 19px;" align="center">
                                <td style="width: 33%; height: 19px;" align="right">
                        <asp:TextBox ID="frmFields" runat="server" BorderStyle="None" Columns="30">Name</asp:TextBox><asp:TextBox
                            ID="frmFieldLabels" runat="server" BorderStyle="None" Columns="30">Name</asp:TextBox>
                        <asp:TextBox ID="frmSortField" runat="server" Columns="30"></asp:TextBox>
                        <asp:TextBox ID="frmSortDirection" runat="server" Columns="30"></asp:TextBox><br />
                        <br />
                        <br />
                    <asp:AsyncPostBackTrigger ControlID="frmCheckboxCurrentView" EventName="SelectedIndexChanged" />
            <br />

This is the code behind file (test_ppc_creative.aspx.vb):

Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.Configuration
Imports System.Web.HttpRequest
Imports System.Web.HttpContext
Imports System.Collections.Generic

Partial Class ppc_creative
    Inherits System.Web.UI.Page

    Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs)

        ' take actions based on whether there has been a postback
        ' or this is the initial page view

        If Not (Page.IsPostBack) Then
        End If

    End Sub

    Protected Sub doInitialPageLoad()

        ' build checkboxlist
        frmCheckboxCurrentView.Items.Add(New ListItem("Name", "Name"))
        frmCheckboxCurrentView.Items.Add(New ListItem("Age", "Age"))
        frmCheckboxCurrentView.Items.Add(New ListItem("ZipCode", "ZipCode"))

        ' check all checkbox items
        frmCheckboxCurrentView.Items.Item(0).Selected = True
        frmCheckboxCurrentView.Items.Item(1).Selected = True
        frmCheckboxCurrentView.Items.Item(2).Selected = True

        ' set default fields to show
        frmFields.Text = "Name,Age,ZipCode"
        frmFieldLabels.Text = "Name,Age,ZipCode"

        ' fill panel
        ' pass: column names, column titles/headings, sortfield, sortorder
        FillPanel(frmFields.Text, frmFieldLabels.Text)

    End Sub

    Protected Sub doPostBackPageLoad()

        ' fill panel
        FillPanel(frmFields.Text, frmFieldLabels.Text)

    End Sub

    Protected Sub frmCheckboxCurrentView_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles frmCheckboxCurrentView.SelectedIndexChanged

        ' get new columns to display
        Dim myListOfTableColumns As String = String.Empty
        Dim myListOfColumnHeadings As String = String.Empty

        ' find checkboxes that are checked
        Dim myItem As ListItem
        For Each myItem In frmCheckboxCurrentView.Items
            If (myItem.Selected = True) Then
                If Not (myItem.Value.ToString = "") Then
                    myListOfTableColumns &= myItem.Value.ToString & ","
                    myListOfColumnHeadings &= myItem.Text & ","
                End If
            End If

        ' chop off trailing space and comma
        If (myListOfTableColumns.Length > 1) Then
            myListOfTableColumns = Left(myListOfTableColumns, myListOfTableColumns.Length - 1)
            myListOfColumnHeadings = Left(myListOfColumnHeadings, myListOfColumnHeadings.Length - 1)
        End If

        ' if no column headings specified, add default heading
        If String.IsNullOrEmpty(myListOfColumnHeadings) Then
            myListOfTableColumns = "Name"
            myListOfColumnHeadings = "Name"
        End If

        ' save data to text fields
        frmFields.Text = myListOfTableColumns
        frmFieldLabels.Text = myListOfColumnHeadings

        ' fill panel
        FillPanel(myListOfTableColumns, myListOfColumnHeadings)

    End Sub

    ' fill panel 1 with data based on data submitted in form fields

    Public Sub FillPanel(ByVal myDBFieldNames As String, ByVal myColumnNames As String)

        ' get default sort field and direction
        Dim mySortField As String = "Name"
        Dim mySortDirection As String = "ASC"

        ' overwrite if user has specified another sort
        If Not (frmSortField.Text = "") Then
            mySortField = frmSortField.Text
        End If
        If Not (frmSortDirection.Text = "") Then
            mySortDirection = frmSortDirection.Text
        End If

        ' begin table
        Dim myTable As Table = New Table
        myTable.ID = "UpdatePanelTable"
        myTable.CellPadding = "3"
        myTable.CellSpacing = "1"

        ' get data
        Dim myDataTable As DataTable = New DataTable
        myDataTable = GetDataTable()
        Dim myDSEmployees As DataSet = New DataSet

        ' put in dataview to sort
        Dim myDVEmployees As DataView = New DataView
        myDVEmployees = myDSEmployees.Tables(0).DefaultView
        myDVEmployees.Sort = mySortField & " " & mySortDirection

        ' create table header
        ' create table sort buttons on each column
        Dim arDBFieldNames As Array = Split(myDBFieldNames, ",")
        Dim arColumnNames As Array = Split(myColumnNames, ",")
        Dim myTableHeaderRow As TableRow = New TableRow
        myTableHeaderRow.Attributes.Add("bgcolor", "#5D7B9D")
        Dim i, j As Integer
        For i = 0 To arDBFieldNames.Length - 1
            Dim myHeaderRowCell As TableCell = New TableCell
            myHeaderRowCell.Wrap = False

            Dim myHeaderCellText As Label = New Label

            Dim mySortButtonUp As ImageButton = New ImageButton
            mySortButtonUp.ImageUrl = "~/images/btn_sort_up.gif"
            mySortButtonUp.ID = arDBFieldNames(i).ToString & "_DESC"
            mySortButtonUp.Attributes.Add("runat", "server")
            AddHandler mySortButtonUp.Click, AddressOf CreativesSortButton_Click
            'Dim myTrigger1 As PostBackTrigger = New PostBackTrigger
            'myTrigger1.ControlID = mySortButtonUp.UniqueID

            Dim mySortButtonDown As ImageButton = New ImageButton
            mySortButtonDown.ImageUrl = "~/images/btn_sort_down.gif"
            mySortButtonDown.ID = arDBFieldNames(i).ToString & "_ASC"
            mySortButtonDown.Attributes.Add("runat", "server")
            AddHandler mySortButtonDown.Click, AddressOf CreativesSortButton_Click
            'Dim myTrigger2 As PostBackTrigger = New PostBackTrigger
            'myTrigger2.ControlID = mySortButtonUp.UniqueID

            myHeaderCellText.Text = arColumnNames(i).ToString & "<br>"
            myHeaderRowCell.ForeColor = Drawing.Color.White
            myHeaderRowCell.Font.Bold = True



        ' create table data
        For i = 0 To myDSEmployees.Tables(0).Rows.Count - 1
            Dim myRow As TableRow = New TableRow
            For j = 0 To arDBFieldNames.Length - 1
                Dim myCell As TableCell = New TableCell
                myCell.Text = myDSEmployees.Tables(0).Rows(i).Item(arDBFieldNames(j)).ToString

        ' create panel to hold table
        Dim myPanelCreatives As Panel = New Panel
        myPanelCreatives.Width = 950
        myPanelCreatives.ScrollBars = ScrollBars.Horizontal

        ' add table to panel

    End Sub

    Protected Sub CreativesSortButton_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs)

        Dim myData As String = String.Empty
        myData = sender.id.ToString
        Dim arData As Array = Split(myData, "_")

        frmSortField.Text = arData(0)
        frmSortDirection.Text = arData(1)

        ' fill panel
        ' FillPanel(frmFields.Text, frmFieldLabels.Text)

    End Sub

    ' creates data table
    ' normally done by call to database

    Protected Function GetDataTable() As DataTable

        'creating table
        Dim myDataTable As DataTable
        myDataTable = New DataTable("Employees")

        ' three rows for the table
        Dim Row1, Row2, Row3 As DataRow

        ' three columns
        Dim Name As DataColumn = New DataColumn("Name")
        Name.DataType = System.Type.GetType("System.String")
        Dim Product As DataColumn = New DataColumn("Age")
        Product.DataType = System.Type.GetType("System.String")
        Dim Location As DataColumn = New DataColumn("ZipCode")
        Location.DataType = System.Type.GetType("System.String")

        ' row 1
        Row1 = myDataTable.NewRow()
        Row1.Item("Name") = "Andy"
        Row1.Item("Age") = "40"
        Row1.Item("ZipCode") = "33333"

        ' row 2
        Row2 = myDataTable.NewRow()
        Row2.Item("Name") = "Barry"
        Row2.Item("Age") = "30"
        Row2.Item("ZipCode") = "22222"

        ' row 3
        Row3 = myDataTable.NewRow()
        Row3.Item("Name") = "Clyde"
        Row3.Item("Age") = "35"
        Row3.Item("ZipCode") = "11111"

        ' return datatable
        Return myDataTable

    End Function

End Class
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

redzoneglobalAuthor Commented:
I finaly figured this out thanks to this post:

I had to modify my code:

Dim mySortButtonUp As ImageButton = New ImageButton
mySortButtonUp.ImageUrl = "~/images/btn_sort_up.gif"
mySortButtonUp.ID = arDBFieldNames(i).ToString & "_DESC"
mySortButtonUp.Attributes.Add("runat", "server")
AddHandler mySortButtonUp.Click, AddressOf CreativesSortButton_Click
'Dim myTrigger1 As PostBackTrigger = New PostBackTrigger
'myTrigger1.ControlID = mySortButtonUp.UniqueID

To this:

Dim mySortButtonDown As ImageButton = New ImageButton
mySortButtonDown.ImageUrl = "~/images/btn_sort_down.gif"
mySortButtonDown.ID = arDBFieldNames(i).ToString & "_ASC"
mySortButtonDown.Attributes.Add("runat", "server")
mySortButtonDown.OnClientClick = "__doPostBack('UpdatePanelCreatives','" & arDBFieldNames(i).ToString & "_DESC" & "')"

to force a postback on the updatepanel. And I did the same thing on the code creating the other sort button.

Then I had to call the doPostBackPageLoad() in the Page_Load sub conditionally like this:

       If (Request.Form("__EVENTTARGET").ToString = "UpdatePanelCreatives") Then
                Dim myData As String = String.Empty
                myData = Request.Form("__EVENTARGUMENT").ToString
                Dim arData As Array = Split(myData, "_")

                frmSortField.Text = arData(0)
                frmSortDirection.Text = arData(1)

            End If

If you happen to be doing this using master pages (which I am in my original code) you will have to provide the full namd/ID of your update panel in your __doPostBack call or you'll get a full page postback, rather than only an updatepanel refresh.

I used a recursive findcontrol function that I modified from something I found on the web, like this:

Public Shared Function FindControlIterative(ByVal myRoot As Control, ByVal myIDOfControlToFind As String) As Control

            Dim myRootControl As Control = New Control
            myRootControl = myRoot
            Dim setOfChildControls As LinkedList(Of Control) = New LinkedList(Of Control)

            Do While (myRootControl IsNot Nothing)
                If myRootControl.ID = myIDOfControlToFind Then
                    Return myRootControl
                End If
                For Each childControl As Control In myRootControl.Controls
                    If childControl.ID = myIDOfControlToFind Then
                        Return childControl
                    End If
                    If childControl.HasControls() Then
                    End If
                myRootControl = setOfChildControls.First.Value

            Return Nothing

End Function

and called it like:

Dim myUpdatePanelCreatives As UpdatePanel = New UpdatePanel
myUpdatePanelCreatives = FindControlIterative(Page, "UpdatePanelCreatives")

This may not be the most elegent solution, but it works.
I hope this helps someone else.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
can i get same solution in C# code for same question
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.