我正在使用 asp 转发器来显示名称列表,并且我想将当前字母显示为一种分组标题,就像在索引页面中一样。
数据在绑定之前按字母顺序排序,但我发现在显示名称之前很难插入“A”和“B”。
在绑定之前进行排序。
即绑定排序后的结果集。
然而,如果没有看到你所拥有的价值观,就不可能确切地知道如何做到这一点。
更新-根据您的评论,我会说您需要将绑定源更改为类似Dictionary<string,IList<string>>
.
使用这样的结构,您可以通过键(排序)和子列表(二级排序)进行绑定。
将 Panel 控件添加到您的 ItemTemplate,并将可见性设置为 False。当您绑定中继器时(假设您正在订阅ItemDataBound
事件),运行检查以查看第一个字母是否已更改。如果有,请将面板的可见性设置为 true 并打印出该字母。
如果您需要一些示例代码,请告诉我。
编辑:示例代码
为清楚起见,“AlphaHeaders”就是我们要显示的“A”、“B”、“C”字母
aspx 代码
中继器将如下所示:
<table>
<asp:Repeater id="rptRepeater" runat="server" OnItemDataBound="rptNames_OnItemDataBound">
<ItemTemplate>
<asp:Panel id="pnlAlphaHeader" runat="server" visible="False">
<tr><td><asp:Label id="lblAlphaHeader" runat="server" /></td></tr>
</asp:Panel>
<tr><td><asp:Label id="lblName" runat="server" /></td></tr>
</ItemTemplate>
</asp:Repeater>
</table>
aspx.cs 代码
首先,您需要一个保存当前 AlphaHeader 的变量:
private string _AlphaHeaderCurrent = String.Empty;
然后,您将对转发器的OnItemDataBound
事件进行处理:
protected void rptNames_OnItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if ((e.ItemType==ListItemType.Item) || (e.ItemType==ListItemType.AlternatingItem)) {
string name = e.Item.DataItem("Name").ToString();
//check if the first letter of the current name is new. If it is new, we print out the header
if(!name.StartsWith(this._AlphaHeaderCurrent)) {
this._AlphaHeaderCurrent = name.SubString(1);
((Panel)e.ItemFindControl("pnlAlphaHeader")).Visible = true;
((Label)e.Item.FindControl("lblAlphaHeader")).Text = the._AlphaHeader;
}
((Label)e.Item.FindControl("lblName")).Text = name;
}
}
在将数据绑定到中继器之前,您需要对数据进行排序。
您可以使用嵌套中继器(中继器内的中继器)。像类别和子类别。在第一个中继器中,您可以列出所有名称并以 A 开头。然后在子中继器中,您可以显示所有名称。您还将使用 itemdatabound 事件绑定第二个中继器。
<asp:Repeater id="rptFirstLetters" runat="server" OnItemDataBound="rptChars_OnItemDataBound">
<ItemTemplate>
<div>"<%#Eval("letters") %>"
<asp:Repeater id="rptNames" runat="server">
<ItemTemplate>
<%#Eval("names") %>
</ItemTemplate>
</asp:Repeater>
</div> // bind all letters
</ItemTemplate>
老实说,这并不是一个很好的方法,中继器通常会导致我发现的丑陋代码。如果可以设置,来自 kad1r 的分层方法可能是最好的,但也有其他选择,具体取决于您的实现细节;我在某些方面更喜欢这个,因为它可以保持标记非常干净,而且我有一个非程序员设计人员,这对我来说是一个加分项。
ASPX:
<%@ Page language="C#" Src="test.CODE.cs" Inherits="test_Page" %>
<asp:Repeater ID="TestRepeater" runat="server">
<ItemTemplate>
<asp:PlaceHolder Visible='<%# Eval("IsFirstInGroup") %>' runat="server">
<strong><%# Eval("Initial") %></strong><br/>
</asp:PlaceHolder>
<%# Eval("Name") %><br/>
</ItemTemplate>
</asp:Repeater>
代码背后:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public class test_Page : Page
{
protected Repeater TestRepeater;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
String[] names = new String[]
{
"Alpha, John",
"Altman, Mary",
"Asher, Cyril",
"Bachman, Turner",
"Beta, Rob",
"Bexman, Norah",
"Clark, Freddy"
};
List<_DispItem> l = new List<_DispItem>();
for (int i = 0; i < names.Length; i++)
l.Add(new _DispItem() { Name = names[i], IsFirstInGroup = (i == 0 || names[i - 1][0] != names[i][0]) });
TestRepeater.DataSource = l;
TestRepeater.DataBind();
}
private class _DispItem
{
public String Name { get; set; }
public String Initial { get { return Name.Substring(0, 1); } }
public bool IsFirstInGroup { get; set; }
}
}