Link to home
Start Free TrialLog in
Avatar of kbailey23342
kbailey23342

asked on

Datagrid Losing Viewstate on Postback

Experts: I'm in need of some help on a datagrid problem I've been chasing for two days now.  I have a datagrid setup with template columns including two link buttons (one called Approve and one called Reject).  When the datagrid binds the first time, the itemcommand event fires just fine for either button.  When the datagrid binds the second time, the itemcommand event DOES NOT fire for either button (nor does any other datagrid event).  When the datagrid binds the third time, the itemcommand event fires just fine, so on and so on.

I am binding to a rather large class with several sub-classes inside.  Again, the databind Appears to work fine for each trip through.   I have viewstate set to true for the datagrid.  I have autoevebtwireup set to false for the page.  I have pagination turned off.

Has anyone else had this similar problem?

I'm running Visual Studio .Net 2003, Windows XP Pro op system,  connecting to a SQL Server backend.  This is my first experience with databinding problems.

Thanks in advance,

kbailey23342
Avatar of raterus
raterus
Flag of United States of America image

Sounds like a dynamic control issue, I bet you are doing something like this when you are binding the grid.

someControlInMyDG.Controls.Add(someOtherControlThatWillNotPersistAcrossAPostbackandWillNotFireEventsUnlessYouDoThisEachTime)
Avatar of kbailey23342
kbailey23342

ASKER

No, I'm not dynamically adding controls to the grid.  All the controls are added via the datagrid creation tool.  The only controls that exist are the two link buttons mentioned above.  Outside of that, there are 8 other fields that deplay data from the class I'm connecting to.

- Kbailey23342
Could you post the source/code?
Can't post until Monday, but will do then...
may be also because you are not doing something like this in page_load

If not page.ispostback = true
  BindGrid()
End If
Here's the entier page scenario: There are two date-picker boxes (beginning date, ending date), and one Refresh button.  The refresh button fires a loaddata method which then fires a binddata method.  The loaddata method loads data into an HTTPContext session variable.  The binddata method retrieves the HTTPContext session variable and binds the grid to that data.  The datagrid contains 10 total columns (including the two link buttons mentioned above).

All controls have enable viewstate set to true.  The date-picker boxes are richdatepicker controls.

- kbailey23342
Post the code when you get a chance, it's probably something very simple.
I'll post the HTML and Code-Behind on Monday.  I have looked over the code and I know it's something simple I've missed.
I am posting the HTML and Code-Behind logic.  Code-Behind is written in VB.Net.

<%@ Register TagPrefix="cc1" Namespace="RicherComponents.DatePickerControl" Assembly="RichDatePicker" %>
<%@ Control Language="vb" AutoEventWireup="false" Codebehind="PTRefundProcessing.ascx.vb" Inherits="ACS.PTRefundProcessingScreen" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<center><asp:datagrid id="ValSum" DESIGNTIMEDRAGDROP="2" runat="server" CssClass="cssDataGrid" width="75%"
AutoGenerateColumns="False" Visible="False" CellPadding="5" CellSpacing="1" GridLines="None" EnableViewState="false">
  <AlternatingItemStyle CssClass="cssDataGridAlternatingItem"></AlternatingItemStyle>
  <ItemStyle CssClass="cssDataGridItem"></ItemStyle>
    <Columns>
      <asp:TemplateColumn HeaderText="Error Message(s)" HeaderStyle-Font-Bold="true">
        <HeaderStyle Width="1%" CssClass="cssDataGridHeader"></HeaderStyle>
        <ItemStyle Wrap="True" Font-Bold="True"></ItemStyle>
        <ItemTemplate>
      <asp:Label ID="msg" Runat="server">
      <%# "• " + Container.DataItem  %>
                </asp:Label>
        </ItemTemplate>
      </asp:TemplateColumn>
    </Columns>
</asp:datagrid></center>
<% if ValSum.Items.Count > 0 Then
      Response.Write("<br>&nbsp;<br>")
   End If
%>
<table id="table1" cellSpacing="0" cellPadding="10" width="100%" border="0">
   <tr>
      <td class="lightBgColor" vAlign="top" width="100%"><span class="BoldHeader"><asp:label id="lblStep" runat="server">Enter a begin and end date to located any refund or 3 day cancel requests.  A listing of PT agreements with requests will be displayed.  By pressing the Approve or Reject link next to the corresponding agreement the request will be updated.</asp:label></span>
      </td>
    </tr>
</table>
<br>
&nbsp;<br>
<table class="cssDataGridItem" id="table2" cellSpacing="0" cellPadding="4" width="100%"
  border="0">
      <tr class="cssDataGridItem">
            <td align="right" width="30%">Begin Date (MM/DD/YYYY):</td>
            <td align="left" width="70%"><asp:textbox id="txtBeginDate" tabIndex="1" runat="server" Width="90px" MaxLength="10"></asp:textbox></td>
      </tr>
      <tr class="cssDataGridItem" align="right">
            <td align="right" width="30%">End Date (MM/DD/YYYY):</td>
            <td align="left" width="70%"><asp:textbox id="txtEndDate" tabIndex="2" runat="server" Width="90px" MaxLength="10"></asp:textbox></td>
      </tr>
      <tr class="cssDataGridItem">
            <td width="30%"></td>
            <td align="left" width="70%"><asp:button id="btnRefresh" tabIndex="3" runat="server" CssClass="buttonOn" Text="Refresh"></asp:button></td>
      </tr>
</table>
<br>
&nbsp;<br>
<table id="table3" cellSpacing="0" cellPadding="4" width="100%" border="0">
<tr>
   <td><asp:datagrid id="dgSearchResults" runat="server" CssClass="cssDataGrid" AutoGenerateColumns="False" CellPadding="5" CellSpacing="1" GridLines="None" Width="100%" PageSize="25" AllowPaging="True" DataKeyField="ID">
       <FooterStyle HorizontalAlign="Center" CssClass="cssDataGridItem"></FooterStyle>
       <EditItemStyle CssClass="cssDataGridItem"></EditItemStyle>
       <AlternatingItemStyle CssClass="cssDataGridAlternatingItem"></AlternatingItemStyle>
       <ItemStyle CssClass="cssDataGridItem"></ItemStyle>
       <Columns>
      <asp:TemplateColumn HeaderText="PT ID">
                    <HeaderStyle HorizontalAlign="Center" Width="5%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Center"></ItemStyle>
          <ItemTemplate>
               <%# databinder.eval(Container.Dataitem, "Id") %>
          </ItemTemplate>
      </asp:TemplateColumn>
          <asp:TemplateColumn HeaderText="Customer Name">
          <HeaderStyle HorizontalAlign="Center" Width="12%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Left"></ItemStyle>
          <ItemTemplate>
             <%# databinder.eval(Container.Dataitem, "PrimaryMember.FullName") %>
          </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Status">
          <HeaderStyle HorizontalAlign="Center" Width="6%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Center"></ItemStyle>
          <ItemTemplate>
               <%# databinder.eval(Container.Dataitem, "Status.Description") %>
          </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Requested By">
          <HeaderStyle HorizontalAlign="Center" Width="12%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Left"></ItemStyle>
          <ItemTemplate>
              <%# databinder.eval(Container.Dataitem, "StatusChangeRequestBy.Fullname") %>
          </ItemTemplate>
          </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Request Date">
          <HeaderStyle HorizontalAlign="Center" Width="8%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Center"></ItemStyle>
          <ItemTemplate>
              <%# databinder.eval(Container.Dataitem, "StatusDate", "{0:MM/dd/yyyy}") %>
          </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Reason">
          <HeaderStyle HorizontalAlign="Center" Width="6%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Center"></ItemStyle>
          <ItemTemplate>
              <%# databinder.eval(Container.Dataitem, "RefundReason.Description") %>
          </ItemTemplate>
          </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Club">
          <HeaderStyle HorizontalAlign="Center" Width="5%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Center"></ItemStyle>
          <ItemTemplate>
               <%# databinder.eval(Container.Dataitem, "Club.Abbreviation") %>
          </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Trainer Name">
          <HeaderStyle HorizontalAlign="Center" Width="12%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Left"></ItemStyle>
          <ItemTemplate>
            <%# databinder.eval(Container.Dataitem, "Trainer.Fullname") %>
          </ItemTemplate>
                 </asp:TemplateColumn>
       <asp:TemplateColumn>
          <HeaderStyle Width="6%" CssClass="cssDataGridHeader"></HeaderStyle>
          <ItemStyle HorizontalAlign="Center"></ItemStyle>
          <ItemTemplate>
               <asp:LinkButton id="lbtnApprove" runat="server" Text="Approve" CommandName="Approve" CausesValidation="false"></asp:LinkButton>
          </ItemTemplate>
       </asp:TemplateColumn>
       <asp:TemplateColumn>
              <HeaderStyle Width="6%" CssClass="cssDataGridHeader"></HeaderStyle>
              <ItemStyle HorizontalAlign="Center"></ItemStyle>
              <ItemTemplate>
                  <asp:LinkButton id="lbtnReject" runat="server" Text="Reject" CommandName="Reject" CausesValidation="false"></asp:LinkButton>
               </ItemTemplate>
       </asp:TemplateColumn>
      </Columns>
      <PagerStyle NextPageText="Next &gt;" PrevPageText="&lt; Previous" HorizontalAlign="Center" ForeColor="Black"       Position="TopAndBottom" BackColor="#FEBF01" Mode="NumericPages"></PagerStyle>
      </asp:datagrid>
    </td>
    </tr>
</table>
Here is the code-behind page:

The following imports are a classes associated with the build of the project.  We're using true OO methodologies on this project:

Imports Lifestyle.Accessor.PT
Imports Lifestyle.Structures.PT
Imports LifeStyle.Entity.pt
Imports LifeStyle.Accessor
Imports Lifestyle.structures
Imports LifeStyle.Entity
Imports LifeStyle.Entity.PT.LookUps
Imports Lifestyle.Enumeration
Imports Lifestyle.Entity.PT.agreement
Imports Microsoft.ApplicationBlocks.ExceptionManagement

Public Class PTRefundProcessingScreen
    Inherits SinglePageAppControl
    Dim oRepresentative As Representative = GetRepresentation(HttpContext.Current)

#Region " Web Form Designer Generated Code "

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

    End Sub
    Protected WithEvents ValSum As System.Web.UI.WebControls.DataGrid
    Protected WithEvents lblStep As System.Web.UI.WebControls.Label
    Protected WithEvents btnRefresh As System.Web.UI.WebControls.Button
    Protected WithEvents dgSearchResults As System.Web.UI.WebControls.DataGrid
    Protected WithEvents txtBeginDate As System.Web.UI.WebControls.TextBox
    Protected WithEvents txtEndDate As System.Web.UI.WebControls.TextBox

    'NOTE: The following placeholder declaration is required by the Web Form Designer.
    'Do not delete or move it.
    Private designerPlaceholderDeclaration As System.Object

    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
        Try
            SetSummary(ValSum)
            If Not IsPostBack Then
                txtBeginDate.Text = Date.Now.ToShortDateString
                txtEndDate.Text = Date.Now.ToShortDateString
                LoadData(Date.Now.Date, Date.Now.Date)
            End If

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex)

        End Try
    End Sub

    Private Sub dgSearchResults_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgSearchResults.ItemCreated
        Try
            SetSummary(ValSum)
            Select Case e.Item.ItemType
                Case ListItemType.Item, ListItemType.AlternatingItem
                    Dim myApproveButton As LinkButton
                    myApproveButton = e.Item.FindControl("lbtnApprove")
                    myApproveButton.Attributes.Add("onclick", "return confirm('Are you sure you want to Approve this item?');")
                    Dim myRejectButton As LinkButton
                    myRejectButton = e.Item.FindControl("lbtnReject")
                    myRejectButton.Attributes.Add("onclick", "return confirm('Are you sure you want to Reject this item?');")
            End Select

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try

    End Sub

    Private Sub dgSearchResults_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgSearchResults.ItemDataBound
        Dim CurrentPTAgreement As PTAgreement
        Dim RefundCollection As PTRefundCollection
        Dim id As Integer
        Dim lnkBtn As LinkButton

        Try
            SetSummary(ValSum)
            If e.Item.ItemType = ListItemType.Item Or _
               e.Item.ItemType = ListItemType.AlternatingItem Then
                RefundCollection = GetListing(HttpContext.Current)
                id = dgSearchResults.DataKeys.Item(e.Item.ItemIndex)
                CurrentPTAgreement = RefundCollection.ViewItem(id)
                ' if the current status is refunded or three day cancelled, then don't display linkbuttons
                If (CurrentPTAgreement.Status.Id = PTStatus.Refunded.Id) Then
                    ' turn off visibility to the approved link button
                    lnkBtn = e.Item.FindControl("lbtnApprove")
                    lnkBtn.Visible = False
                    ' turn off visibility to the rejected link button
                    lnkBtn = e.Item.FindControl("lbtnReject")
                    lnkBtn.Visible = False
                End If
            End If

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try

    End Sub

    Private Sub dgSearchResults_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgSearchResults.ItemCommand
        Dim CurrentPTAgreement As PTAgreement
        Dim RefundCollection As PTRefundCollection
        Dim Approve As Boolean

        Try
            SetSummary(ValSum)
            If e.Item.ItemIndex >= 0 Then
                RefundCollection = GetListing(HttpContext.Current)
                ID = dgSearchResults.DataKeys.Item(e.Item.ItemIndex)
                CurrentPTAgreement = RefundCollection.ViewItem(ID)

                If e.CommandName = "Approve" Then
                    Approve = True
                End If
                If e.CommandName = "Reject" Then
                    Approve = False
                End If

                If CurrentPTAgreement.Status.Id = PTStatus.RefundRequest.Id Then
                    CurrentPTAgreement.RefundProcess(Approve, RefundCollection)
                    Me.SetListing(HttpContext.Current, RefundCollection)
                    BindGrid()
                End If
            End If

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try

    End Sub

    Private Sub btnRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click
        Try
            SetSummary(ValSum)
            Dim tmpBeginDate As Date
            Dim tmpEndDate As Date

            If Trim(txtBeginDate.Text) = "" Then
                AddErrorMessage("Please Enter a beginning date!")
                txtBeginDate.Text = Date.Now.ToShortDateString
            End If
            If Trim(txtEndDate.Text) = "" Then
                AddErrorMessage("Please enter an ending date!")
                txtEndDate.Text = Date.Now.ToShortDateString
            End If
            Try
                tmpBeginDate = CDate(txtBeginDate.Text).ToShortDateString
                tmpEndDate = CDate(txtEndDate.Text).ToShortDateString
                If (tmpBeginDate > tmpEndDate) Then
                    AddErrorMessage("The beginning date must be <= the ending date.")
                End If
            Catch ex As Exception
                AddErrorMessage("The beginning date or ending date is invalid.")
            End Try

            If Me.IsValid Then
                LoadData(tmpBeginDate, tmpEndDate)
            End If

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try

    End Sub

    Private Sub LoadData(ByVal in_BeginDate As Date, ByVal in_EndDate As Date)
        Try
            SetSummary(ValSum)
            Dim RefundCollection As PTRefundCollection

            RefundCollection = PTAgreement.RefundsAvailable(in_BeginDate, in_EndDate, oRepresentative)
            Me.SetListing(HttpContext.Current, RefundCollection)
            BindGrid()

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)

        End Try
    End Sub

    Public Sub BindGrid()
        Try
            SetSummary(ValSum)
            Dim RefundCollection As PTRefundCollection
            Dim al As ArrayList
            RefundCollection = Me.GetListing(HttpContext.Current)
            al = RefundCollection.GetList
            Me.dgSearchResults.DataSource = al
            Me.dgSearchResults.DataBind()

        Catch ex As PTBusinessException
            AddErrorMessage(ex.Message)
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try

    End Sub

    Public Shadows Function GetListing(ByVal oHTTPContext As System.Web.HttpContext) As LifeStyle.Entity.PT.Agreement.PTRefundCollection
        Try
            SetSummary(ValSum)
            Return CType(oHTTPContext.Session("sesPTCollection"), LifeStyle.Entity.PT.agreement.PTRefundCollection)

        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try
    End Function

    Public Shadows Sub SetListing(ByVal oHTTPContext As System.Web.HttpContext, ByVal al As LifeStyle.Entity.PT.Agreement.PTRefundCollection)
        Try
            SetSummary(ValSum)
            oHTTPContext.Session("sesPTCollection") = al
        Catch ex As Exception
            AddErrorMessage(ex.Message)
            ExceptionManager.Publish(ex, True)
        End Try
    End Sub

End Class
I have figured out my own problem.  In the dgSearchResult_itemcommand method, I was not deminsioning ID as an Integer.  ID is set to retrieve the datakey value of the item selected.  Therefore, ID was defaulting to an object instead of an integer.  The object appeared to be removed just fine.  However, the viewstate of the datagrid was messed up each time a command button event was correctly firing because I was removing an object instead of a datarow, I believe.  Can I reward myself the points?  <just kidding>...

- kbailey23342
Naa, you can't get your own points (wouldn't that be nice), but they will refund the points you used to ask the question, Just make a request in Community Support to close the question.
https://www.experts-exchange.com/help.jsp#hi70

--Michael

ASKER CERTIFIED SOLUTION
Avatar of Lunchy
Lunchy
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial