zoukankan      html  css  js  c++  java
  • Repeater排序的三种实现方式

    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

  • 相关阅读:
    Balanced Binary Tree
    Swap Nodes in Pairs
    Reverse Nodes in k-Group
    Reverse Linked List II
    Remove Nth Node From End of List
    Remove Duplicates from Sorted List II
    Remove Duplicates from Sorted List
    Partition List
    Merge Two Sorted Lists
    【Yii2.0】1.2 Apache检查配置文件语法
  • 原文地址:https://www.cnblogs.com/ful1021/p/4804380.html
Copyright © 2011-2022 走看看