1

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

搜索.aspx

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

搜索.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>

搜索.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 的代码。不用说,为了解决这个问题,已经去掉了很多绒毛,但是如果缺少任何有用的东西,请告诉我,我会相应地更新示例。

客户信息.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>

客户信息.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
4

1 回答 1

1

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

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

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

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

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

于 2013-02-19T22:12:31.130 回答