【问题标题】:PagedDataSource not showing data in subsequent pagesPagedDataSource 未在后续页面中显示数据
【发布时间】:2013-01-15 18:46:25
【问题描述】:

这可能有点小,但我还没有弄清楚为什么以下内容不能完全正常工作。用户第一次提交搜索时,搜索结果的第一页会正确显示。但是,当用户尝试使用“上一页”和“下一页”按钮进行导航时,转发器不会显示 DataTable 中的相应数据。

搜索.aspx

<asp:Repeater ID="rptSearchResults" runat="server" OnItemDataBound="rptSearchResults_ItemDataBound">
    <ItemTemplate>
        <div>
            <asp:Literal ID="ltlCustName" runat="server" />
        </div>
    </ItemTemplate>
</asp:Repeater>

search.aspx.vb

Public dtCustomers As DataTable = New DataTable()
Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load
    ' Check to see if this is the first time postback-ing to itself.
    blnFirstPostBack = (Request.Form("firstpb") = "1")

    ' When the page first loads, show the search form with search options.
    If Not Page.IsPostBack Then
        Session("StoredDT") = Nothing
        ShowSearchForm()
    ' Once the form is submitted, show the search results.
    Else
        Response.Write("DEBUG: Get Data")
        If blnFirstPostBack Then
            GatherFormData()
            dtCustomers = BuildDT()
            Session("StoredDT") = dtCustomers
            BindData()
        ElseIf Not Session("StoredDT") Is Nothing Then
            dtCustomers = Session("StoredDT")
        End If
    End If
End Sub

Sub BindData()
    Response.Write("DEBUG: Bind Data")
    ' At this point, I've checked that the dtCustomers is showing the proper data (e.g., grabbing from session when appropriate).
    Dim objPDS As PagedDataSource = New PagedDataSource()
    objPDS.DataSource = dtCustomers.DefaultView
    objPDS.AllowPaging = True
    objPDS.PageSize = intNumPerPage
    ' I've checked that Me.ViewState("_CurrentPage") gets updated to the correct page.
    objPDS.CurrentPageIndex = Me.ViewState("_CurrentPage")
    rptSearchResults.DataSource = objPDS
    ' I'm not sure if the error is here but although the dtCustomers is the proper data, the PagedDataSource and the binding here doesn't seem to play nice.
    Call rptSearchResults.DataBind()
End Sub

' Subroutine called when the previous page button is pressed.
Sub GoToPrevPage()
    Response.Write("DEBUG: Prev Page")
    ' Set viewstate variable to the previous page.
    Me.ViewState("_CurrentPage") -= 1
    BindData()
End Sub

' Subroutine called when the next page button is pressed.
Sub GoToNextPage()
    Response.Write("DEBUG: Next Page")
    ' Set viewstate variable to the next page.
    Me.ViewState("_CurrentPage") += 1
    BindData()
End Sub

Protected Sub rptSearchResults_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptSearchResults.ItemDataBound
    Dim item As RepeaterItem = e.Item
    Dim strCustName As String = ""
    If (item.ItemType = ListItemType.Item) Or (item.ItemType = ListItemType.AlternatingItem) Then
        strCustName = e.Item.DataItem("CustName")
        Dim ltlCustName As Literal = CType(e.Item.FindControl("ltlCustName"), Literal)
        ltlCustName.Text = strCustName
    End If
End Sub

示例页面 1(显示正确的数据):

DEBUG: Get Data
DEBUG: Bind Data
Laurence Clinton
John Doe
Sean King
Jane Smith

示例第 2 页(未显示正确数据,但为缺失数据显示了足够的空间):

DEBUG: Get Data
DEBUG: Next Page
DEBUG: Bind Data
[no name showing here 5]
[no name showing here 6]
[no name showing here 7]
[no name showing here 8]

请原谅缩写的代码,但实际代码很大,所以简化是为了更容易找到问题的核心。

如果其中有任何不清楚或是否需要更多代码,请告诉我。提前致谢!

2013 年 2 月 19 日更新:

所以在稍微修改一下代码之后,我认为错误发生在转发器子例程中。中继器内部的原始文字现在可以使用。出于某种原因,我认为它以前不起作用,但现在可以正常工作。问题是当我们在转发器子例程中使用自定义控件更进一步时。似乎信息没有传递到控件中。控件被正确调用,因为仅在控件中找到的支持 HTML 被正确输出,但我们尝试传递到控件中的客户信息没有进入控件内部。这是修改后的代码:

搜索.aspx

<asp:Repeater ID="rptSearchResults" runat="server" OnItemDataBound="rptSearchResults_ItemDataBound">
    <ItemTemplate>
        <div>
            <asp:Literal ID="ltlCustName" runat="server" />
            <Acme:CustInfo ID="AcmeCustInfo" runat="server" />
        </div>
    </ItemTemplate>
</asp:Repeater>

search.aspx.vb

Protected Sub rptSearchResults_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptSearchResults.ItemDataBound
    Dim item As RepeaterItem = e.Item
    Dim strCustName As String = ""
    If (item.ItemType = ListItemType.Item) Or (item.ItemType = ListItemType.AlternatingItem) Then
        strCustName = e.Item.DataItem("CustName")

        ' This literal properly shows the customer name on subsequent pages so the customer name reaches this point properly.
        Dim ltlCustName As Literal = CType(e.Item.FindControl("ltlCustName"), Literal)
        ltlCustName.Text = strCustName

        ' This control gets called properly but strCustName doesn't 
        ' get passed into the control. The control works fine for the
        ' first page but subsequent pages do not work. Also, the 
        ' control works fine when PagedDataSource is not used.
        Dim AcmeCustInfo As CustInfo = CType(e.Item.FindControl("AcmeCustInfo"), CustInfo)
        AcmeCustInfo.CustName = strCustName
    End If
End Sub

根据安的要求

这是 CustInfo 的代码。不用说,为了解决这个问题,我们已经去掉了很多多余的东西,但是如果缺少任何有用的东西,请告诉我,我会相应地更新示例。

custinfo.ascx

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="CustInfo.ascx.vb" Inherits="CustInfo" %>

<div style="border: 1px solid black;">
    <asp:Literal ID="ltlCustName" runat="server" />
</div>

custinfo.ascx.vb

Imports System
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports System.Web.HttpUtility

Partial Class CustInfo
    Inherits System.Web.UI.UserControl

    Private _CustName As String = ""

    Public Property CustName() As String
        Get
            Return _CustName
        End Get
        Set(value As String)
            _CustName = value
        End Set
    End Property

    Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load
        Dim ltlCustName As Literal = CType(FindControl("ltlCustName"), Literal)
        ltlCustName.Text = "<b>Name: " & CustName & "</b>"
    End Sub
End Class

【问题讨论】:

  • bump 看看有没有人有什么建议?
  • 你能给我们看看AcmeCustomControl吗?具体来说:CustName 属性的声明(以及它的后备存储是什么)以及如何呈现 CustName 和其他信息?
  • 当然可以。我已经添加了上面的代码。感谢 Ann L. 观看。

标签: asp.net vb.net datatable


【解决方案1】:

我不是PagedDataSource 专家,但我已广泛使用用户控件。

您在Load 子例程中的CustInfo 控件中设置文字的值。如果我没记错的话,那将在创建 CustInfo 控件时被调用。这会在调用 OnItemDataBound 之前发生,所以 -- 我 认为 -- Load 子例程将会发生,并且在您分配值之前将文字的值设置(为空字符串) CustName 属性。要解决此问题,请稍后尝试设置文字的值,例如在 PreRender 子例程中。

看起来您在每次回发时都具有约束力,因此以下问题应该不是问题,但如果不是,这里有一些可能会影响您的事情:

  1. ItemDataBound 仅在您重新绑定时运行。如果您为转发器打开了 ViewState,则将在回发时重新创建控件,并且 ItemCreated 将运行,但 ItemDataBound 不会运行。所以你永远不会重新设置你的 CustName 属性。这很重要,因为...
  2. ...您的CustName 属性有一个变量作为后备存储:它没有保存在ViewState 中。因此,当重新创建用户控件时,您之前设置的CustName 属性将不再存在:您的文字内容将设置为空字符串,即CustName 属性的默认值。

这两者加在一起会完全符合您所描述的行为。但是,由于看起来您确实绑定了每个回发(最终),这可能不是问题。为了完整起见,我将其包括在内。

【讨论】:

  • Ann L.,你太棒了! PreRender 建议奏效了。我基本上只是改变了这一行:Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.LoadPublic Sub Page_PreRender(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.PreRender 并且它可以正常工作。再次感谢你!注:是的,我的意图是绑定每个回发。我认为这是必要和适当的吧?
  • 是否有必要取决于您是否需要对页面更改做出反应(而且我对 PagedDataSource 的了解还不够,无法确定),但似乎合适。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
  • 2019-09-07
  • 2021-07-26
  • 2020-05-09
相关资源
最近更新 更多