Repeater排序的三种实现方式

来源:互联网 发布:如何处理tsv数据 编辑:程序博客网 时间:2024/05/29 04:32

Repeater控件是较为干净的服务端数据控件,它不像GridView已经包含了分页和排序功能,这两个小功能都要咱们自己去实现。由于分页的功能很容易实现,我也没什么好讲的;下文中我提供了三种排序方式,除了传统方式以外,另外两种都较为简便灵活。

在线Demo:

  1. Demo - Repeater 传统排序
  2. Demo - Repeater 反射排序方式
  3. Demo - Repeater Linq 扩展方法排序方式

本篇文章已经同步至我的个人博客站点:积累吧 |Repeater排序的三种实现方式(附在线Demo),这里有更好的博客视觉体验。

1. 数据准备

数据库Test,表名Books,下图是表结构,在Books表中我准备了100条测试数据。

image

在页面上除了Id以外其它字段都会被显示。Repeater的数据源由NHibernate下的Repository模式提供,由于只有一个表而且给出了表图,Book.cs和Book.hbm.xml代码我不会贴出来。

在将要进行的几种Demo中都包含下面4个代码片段,如果大家对这4个片段不感兴趣,可以直接略过去,直接跳转到:

  • 传统排序方式
  • 反射排序方式
  • 扩展方法排序方式

 

片段1:获取数据源,缓存

#region Properties/// <summary>/// Book仓储器/// </summary>private IBookRepository BookRepository{    get { return new BookRepository(); }}/// <summary>/// Cache缓存数据源/// </summary>private IList<Book> DataSource{    get { return Cache["_data"] as IList<Book>; }    set    {        if (Cache["_data"] == null)        {            Cache["_data"] = value;        }    }}#endregion

片段2:绑定Repeater

#region Private Methods/// <summary>/// 绑定Repeater/// </summary>private void BindRepeater(){    if (DataSource == null)    {        IList<Book> books = BookRepository.GetAll().ToList();        DataSource = books;    }    // 首次加载时绑定数据源    if(ViewState["SortOrder"] == null)    {        this.Repeater1.DataSource = DataSource;        this.Repeater1.DataBind();    }}#endregion

片段3:排序设置

/// <summary>/// 设置排序字段、排序方式、排序文本/// </summary>private void SetSorting(RepeaterCommandEventArgs e){    var sort = (LinkButton)e.Item.FindControl(e.CommandName.Trim());    if (e.Item.ItemType == ListItemType.Header)    {        string sortText = string.Empty;        // 存储排序字段、排序方式、排序文本        if (ViewState["SortOrder"] == null || ViewState["SortBy"].ToString() != e.CommandName)        {            ViewState["SortOrder"] = "ASC";            ViewState["SortBy"] = e.CommandName;            sortText = sort.Text + "▲";        }        else        {            ViewState["SortOrder"] = ViewState["SortOrder"].ToString() == "ASC" ? "DESC" : "ASC";            // 排序时更改文本            if (sort.Text.IndexOf("▲") == -1)            {                if (sort.Text.IndexOf("▼") == -1)                    sortText = sort.Text + "▲";                else                    sortText = sort.Text.Replace("▼", "▲");            }            else            {                sortText = sort.Text.Replace("▲", "▼");            }        }        ViewState["SortText"] = sortText;    }}

片段4:前端数据源解析

<table>        <asp:Repeater runat="server" ID="Repeater1" OnItemCommand="Repeater1_ItemCommand"            OnItemDataBound="Repeater1_ItemDataBound">            <HeaderTemplate>                <tr>                    <th width="100">                        <asp:LinkButton ID="ISBN" runat="server" Text="ISBN" CommandName="ISBN" />                    </th>                    <th width="200">                        <asp:LinkButton ID="Title" runat="server" Text="Title" CommandName="Title" />                    </th>                    <th width="100">                        Image                    </th>                    <th width="100">                        <asp:LinkButton ID="Category" runat="server" Text="Category" CommandName="Category" />                    </th>                    <th width="100">                        <asp:LinkButton ID="Author" runat="server" Text="Author" CommandName="Author" />                    </th>                    <th width="100">                        <asp:LinkButton ID="Price" runat="server" Text="Price" CommandName="Price" />                    </th>                    <th width="100">                        <asp:LinkButton ID="Package" runat="server" Text="Package" CommandName="Package" />                    </th>                    <th width="100">                        <asp:LinkButton ID="Pages" runat="server" Text="Pages" CommandName="Pages" />                    </th>                </tr>                <tr>                    <td colspan="8" style="border-bottom: 1px solid #465c71">                    </td>                </tr>            </HeaderTemplate>            <ItemTemplate>                <tr>                    <td width="100">                        <%# Eval("ISBN") %>                    </td>                    <td width="200">                        <%# Eval("Title") %>                    </td>                    <td width="100">                        <img src="<%# Eval("ImageUrl") %>" width="50" />                    </td>                    <td width="100">                        <%# Eval("CategoryName") %>                    </td>                    <td width="100" >                        <%# Eval("Author") %>                    </td>                    <td width="100" >                        <%# Eval("Price") %>                    </td>                    <td width="100" >                        <%# Eval("Package") %>                    </td>                    <td width="100" >                        <%# Eval("Pages") %>                    </td>                </tr>                <tr>                    <td colspan="8" style="border-bottom: 1px solid #465c71">                    </td>                </tr>            </ItemTemplate>        </asp:Repeater>    </table>

2. 传统排序方式

在线Demo浏览:Repeater传统排序方式

protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e){    // 设置排序    SetSorting(e);    if (ViewState["SortOrder"] != null)    {        string sortOrder = ViewState["SortOrder"].ToString();        switch (ViewState["SortBy"].ToString())        {            case "ISBN":                Repeater1.DataSource = sortOrder == "ASC"                                            ? DataSource.OrderBy(b => b.ISBN)                                            : DataSource.OrderByDescending(b => b.ISBN);                break;            case "Title":                Repeater1.DataSource = sortOrder == "ASC"                                            ? DataSource.OrderBy(b => b.Title)                                            : DataSource.OrderByDescending(b => b.Title);                break;            case "Category":                Repeater1.DataSource = sortOrder == "ASC"                                            ? DataSource.OrderBy(b => b.CategoryName)                                            : DataSource.OrderByDescending(b => b.CategoryName);                break;            case "Author":                Repeater1.DataSource = sortOrder == "ASC"                                            ? DataSource.OrderBy(b => b.Author)                                            : DataSource.OrderByDescending(b => b.Author);                break;            case "Package":                Repeater1.DataSource = sortOrder == "ASC"                                            ? DataSource.OrderBy(b => b.Package)                                            : DataSource.OrderByDescending(b => b.Package);                break;            case "Pages":                Repeater1.DataSource = sortOrder == "ASC"                                            ? DataSource.OrderBy(b => b.Pages)                                            : DataSource.OrderByDescending(b => b.Pages);                break;        }        Repeater1.DataBind();    }} 

这段代码是不是看起来很悲催?这么多的Switch Case语句,如果Book类的显示字段增加了,并且都要求排序,那岂不是又得来更改这个方法 。我们想要的方式是只要知道字段的名称(e.CommandName),就能通过几行代码实现排序。反射听起来是个不错的方式。

3. 使用反射获取排序字段

在线Demo:Repeater 反射排序方式

通过反射动态获取Book对象的属性的值,可以将上面的方法精简很多代码。

protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e){    // 设置排序    SetSorting(e);    if (ViewState["SortOrder"] != null)    {        Repeater1.DataSource = ViewState["SortOrder"].ToString() == "ASC"                                    ? DataSource.OrderBy(                                        o => TypeHelper.GetPropertyValue(o, ViewState["SortBy"].ToString()))                                    : DataSource.OrderByDescending(                                        o => TypeHelper.GetPropertyValue(o, ViewState["SortBy"].ToString()));        Repeater1.DataBind();    }}

Type类代码:

public static class TypeHelper{    public static object GetPropertyValue(object obj, string name)    {        return obj == null ? null : obj.GetType()                                        .GetProperty(name)                                        .GetValue(obj, null);    }}

4.  通过扩展方法让Linq支持字符串排序

在线Demo:Repeater Linq 扩展方法排序方式

Linq本身不支持字符串排序的,在Linq下我们并不能像这样去写代码:

Repeater1.DataSource = DataSource.OrderBy(e.CommandName).ToList();

VS会提示语法错误,因为e.CommandName是string类型,而它需要的是<TSource, TKey>参数。

但是我们可以通过扩展方法去达到这一目的。

在项目下添加一个LinqExtension类:

public static class LinqExtension{    public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)    {        string[] sortParts = sortExpression.Split(' ');        var param = Expression.Parameter(typeof (T), string.Empty);        try        {            var property = Expression.Property(param, sortParts[0]);            var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof (object)), param);            if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))            {                return source.AsQueryable<T>().OrderByDescending<T, object>(sortLambda);            }            return source.AsQueryable<T>().OrderBy<T, object>(sortLambda);        }        catch (ArgumentException)        {            return source;        }    }}

sortExpression同时包含了排序字段和排序方式,传入参数时像”Name desc”这种形式。调用的方式很简单,仅一行代码:

protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e){    // 设置排序    SetSorting(e);    if (ViewState["SortOrder"] != null)    {        Repeater1.DataSource = DataSource.Sort(string.Concat(e.CommandName, " ", ViewState["SortOrder"].ToString()));        Repeater1.DataBind();    }}

5. 总结

本文借Repeater排序这个小功能点,介绍了传统的实现方式,但并不灵活,然后介绍了在此基础上改进的反射排序方式,最后又提供了扩展方法实现排序的方式。


原文:http://www.cnblogs.com/keepfool/archive/2012/03/18/2405164.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 \\\\\\\\/favicon.ico JProfiler 趁女兄弟青涩,忽悠她给我生孩子 长生家族:吾儿让吾有大帝之资 纵横诸天,从尸兄开始 从一人开始做七罪之人 苟在分身之后成就神魔 汉末波涛之逐鹿 假面骑士:从在海姆冥界种树开始 魔卡时代:能印卡的我为所欲为 影视世界从都挺好开始 剑斩飞升 道长收敛点,国家快编不下去了 三体:我在诸天攀科技 忍界:要来只念兽吗 从刷经验开始修仙 斗罗:七杀成神 四合院:硬刚到底 天命执刀人 宇智波吉影想要平静地生活 校长只想扣大棚 我的仙兽不可能这么可爱 开局奖励小李飞刀 龙族:去贴吧进修的路明非 https://www.csdndocs.com/focus/show/2428516/1 自武动乾坤开始 提瓦特:逃到蒙德的我捡到莫娜 灭族之夜?无所谓,我会出手 斗罗:娶妻成神,多子多福 综网大玩家 三国:你管这叫文弱谋士?! 别人修机甲,只有我修仙 诸天为王,从庆国太子李承乾开始 我,此世唯一超凡 攻略说,我好像是反派之主 神印王座之血骑士 大主宰之陆天尊 北凉世子:开局签到三千暗影刺客 四合院之一代传奇 高武:我执掌昆虫进化卷轴 系统到账,我直接开摆!