经典场景:获取用户输入,获取搜索结果并将其以页面形式显示给用户。然后我需要显示First,Next,Previous等按钮,并在viewstate中维护用户当前页面。一切都很好,工作正常。
然后我需要实现可点击的页码,即。 1-2-3-4-5-6等。
渲染它们很简单。我在运行时生成一个linkbutton控件,添加带有页码的commandargument并为其添加一个处理程序,因此单击将被处理。然后我将它添加到占位符,并按预期显示。
但是......如果我还没有剃光头,我会拔出头发,每次都按照预期发射事件。
我应该怎么做,所以我的事件总是被连线并且能够在调用分页链接按钮时触发?
下面是代码的重要部分,有些是伪造的(希望)更容易理解,我正在做什么。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Search()
End If
End Sub
Sub Search
'Misc databinding stuff, searches and displays results for the page specified in Me.CurrentPage
RenderPagingControls()
End Sub
Sub RenderPagingControls
'loop throug pagenumbers, Build a linkbutton control, add it to a placeholder
AddHandler lbn.Click, AddressOf lbnNumber_Click
lblPageNumbers.Controls.Add(lbn)
...
End Sub
Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim b As LinkButton = CType(sender, LinkButton)
Me.CurrentPage = CInt(b.CommandArgument)
Search()
End Sub
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.ViewState("CurrentPage")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("CurrentPage") = value
End Set
End Property
Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim b As LinkButton = CType(sender, LinkButton)
Me.CurrentPage = CInt(b.CommandArgument)
Search()
End Sub
答案 0 :(得分:2)
我建议不要使用LinkButton并建议使用Hyperlinks / QueryString参数。有几个原因:
你会将你的CurrentPage方法重新定义为(希望这是正确的,我在C#比vb.net更好):
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.Request.QueryString("page")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
End Property
然后只需为每个页面添加超链接。
<a href='mypage.aspx?page=1'>1</a> - <a href='mypage.aspx?page=2'>2</a>
etc...
替代方法:如果您想使用LinkButton,您可能需要考虑在转发器中放置一个LinkButton。然后,您唯一需要担心的事件是OnItemCommand事件。然后没有动态控件或事件。像这样:
<asp:Repeater ID="rptPages" runat="server" OnItemCommand='doPaging'>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" Text='<%# (Container.DataItem).ToString() %>'
CommandArgument='<%# (Container.DataItem).ToString() %>' />
</ItemTemplate>
<SeparatorTemplate>-</SeparatorTemplate>
</asp:Repeater>
将此控件绑定到连续整数的数组(或列表)(有许多页面)。然后在你的doPaging函数中(我称之为),检查RepeaterCommandEventArgs.CommandArgument以获取页码。
答案 1 :(得分:1)
谢谢你的回答,伙计们。我首先尝试了Austins,但我必须遗漏一些东西,因为我每次都只能使用链接按钮的相同行为...所以我放弃了,并且看到了Keltex的转发器的替代解决方案!它既简单又精彩,我们不必担心任何页面生命周期废话。
它真的有效! ;)
如果将来有人需要类似的东西,这里有相关的幕后代码:
Sub Search()
...
RenderPagingControls()
End Sub
Sub RenderPagingControls()
Dim pages As New ArrayList
For i As Integer = 1 To Me.PageCount
pages.Add(i)
Next
repPageNumbersTop.DataSource = pages
repPageNumbersTop.DataBind()
repPageNumbersBottom.DataSource = pages
repPageNumbersBottom.DataBind()
End Sub
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.ViewState("CurrentPage")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("CurrentPage") = value
End Set
End Property
Public Property PageCount() As Integer
Get
Dim o As Object = Me.ViewState("PageCount")
If o Is Nothing Then
Return 0
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("PageCount") = value
End Set
End Property
Protected Sub repPageNumbersTop_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles repPageNumbersTop.ItemCommand, repPageNumbersBottom.ItemCommand
Me.CurrentPage = CType(e.CommandArgument, Integer)
Search()
End Sub
Private Sub repPageNumbersTop_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repPageNumbersTop.ItemDataBound, repPageNumbersBottom.ItemDataBound
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
Dim lbn As LinkButton = CType(e.Item.FindControl("lbnPageNumber"), LinkButton)
If lbn.CommandArgument = Me.CurrentPage.ToString Then
lbn.Enabled = False
End If
End If
End Sub
答案 2 :(得分:0)
此代码有效(抱歉,它在C#中):
protected void SearchButton_Click(object sender, EventArgs e)
{
//clear the collection!
pnlPageNumber.Controls.Clear();
//simulate search
System.Random rnd = new Random();
//create page buttons
for (int i = 0; i < rnd.Next(3, 15); i++)
{
LinkButton lb = new LinkButton();
pnlPageNumber.Controls.Add(lb);
lb.ID = "btn" + i;
lb.Text = i.ToString();
lb.CommandArgument = i.ToString();
lb.Command += new CommandEventHandler(linkbutton_Command);
//optional literal
pnlPageNumber.Controls.Add(new LiteralControl(" "));
}
ViewState["control#"] = Panel1.Controls.Count;
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
//Recreate link buttons
//This is necessary to ensure proper event binding
int count = 0;
if (ViewState["control#"] != null)
count = (int)ViewState["control#"];
for (int i = 0; i < count; i++)
{
LinkButton lb = new LinkButton();
pnlPageNumber.Controls.Add(lb);
lb.ID = "btn" + i; //make sure IDs are the same here and on Search
lb.Command += new CommandEventHandler(linkbutton_Command);
//this is not necessary, but if you do, make sure its in both places
pnlPageNumber.Controls.Add(new LiteralControl(" "));
}
}
}
void linkbutton_Command(object sender, CommandEventArgs e)
{
Response.Write(e.CommandArgument.ToString() + " CLICK<br />");
}
答案 3 :(得分:0)
您可以使用DataPager控件 - 唯一的限制是您必须将它与ListView控件一起使用,但您应该能够非常轻松地使用ListView控件来表示您的数据,因为它非常灵活。您可以将ListView控件的DataSource设置为数据结果的结果,无论是DataSet,Collection,Array等。
要使用“first”,“last”和页码创建分页控件,请像这样设置DataPager(其中ListView1是ListView控件的ID):
<asp:DataPager ID="DataPager1" runat="server"
PagedControlID="ListView1" PageSize="25">
<Fields>
<asp:NextPreviousPagerField FirstPageText="first" ShowFirstPageButton="True"
ShowNextPageButton="False" ShowPreviousPageButton="False" />
<asp:NumericPagerField />
<asp:NextPreviousPagerField LastPageText="last" ShowLastPageButton="True"
ShowNextPageButton="False" ShowPreviousPageButton="False" />
</Fields>
</asp:DataPager>
按照设计,DataPager使用数据库中的整个结果集,但您可以通过缓存结果并将其用于后续请求来提高性能。
希望这有帮助。
答案 4 :(得分:-1)
iirc ...在运行时动态添加控件有点棘手。必须在回发期间重建控制树...但是在加载viewstate之前(不确定何时在页面生命周期中......但是在页面加载之前)。所以...你的问题是,当asp.net试图找出你的事件时,还没有创建实际的原始控件。