2013-01-15 21 views
1

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

search.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才能正确输出,但我们试图传入控件的客户信息不会进入内部。下面是修改后的代码:

search.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 
+0

*凹凸*看到有没有人有任何建议? – jiminy

+0

你能告诉我们任何'AcmeCustomControl'吗?具体来说:CustName属性的声明(以及它的后备存储是什么)以及如何呈现CustName和其他信息? –

+0

当然。我已经添加了上面的代码。谢谢你安L看看。 – jiminy

回答

1

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

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

它看起来像你在每一个回传结合,所以下面的不应该是一个问题,但如果你不是,这里有一些事情可能会影响您:

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

这两者合起来会给出你描述的行为。但是,因为它看起来像你绑定每一个回传(最终),可能不是问题。我包括它的完整性。

+0

Ann L.,你太棒了! PreRender的建议起作用。我基本上只是改变了这一行: '公共小组的Page_Load(BYVAL发件人为对象,BYVALË作为EventArgs的)把手Me.Load' 到 '公用Sub Page_PreRender(BYVAL发件人为对象,BYVALË作为EventArgs的)把手Me.PreRender ' ,它的工作原理应该如此。再次感谢你! N.B.是的,我的意图是在每一次回传中都有约束力。我认为这是必要和恰当的权利? – jiminy

+0

是否有必要取决于您是否需要对页面更改作出反应(并且我对PagedDataSource的了解不足),但看起来合适。 –

+0

好的,再次感谢你。 – jiminy