加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

Repeater排序的三种实现方式(附在线Demo)

发布时间:2020-12-15 21:25:23 所属栏目:asp.Net 来源:网络整理
导读:Repeater控件是较为干净的服务端数据控件,它不像GridView已经包含了分页和排序功能,这两个小功能都要咱们自己去实现。由于分页的功能很容易实现,我也没什么好讲的;下文中我提供了三种排序方式,除了传统方式以外,另外两种都较为简便灵活。 在线Demo:

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

在线Demo:

本篇文章已经同步至我的个人博客站点: | ,这里有更好的博客视觉体验。

1. 数据准备

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

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

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

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

Properties

<span style="color: gray">///


/// <span style="color: green">Book仓储器
<span style="color: gray">///

<span style="color: blue">private <span style="color: #2b91af">IBookRepository BookRepository
{
<span style="color: blue">get { <span style="color: blue">return new <span style="color: #2b91af">BookRepository(); }
}

<span style="color: gray">///


/// <span style="color: green">Cache缓存数据源
<span style="color: gray">///

<span style="color: blue">private <span style="color: #2b91af">IList<<span style="color: #2b91af">Book> DataSource
{
<span style="color: blue">get { <span style="color: blue">return Cache[<span style="color: #a31515">"_data"] <span style="color: blue">as <span style="color: #2b91af">IList<<span style="color: #2b91af">Book>; }
<span style="color: blue">set
{
<span style="color: blue">if (Cache[<span style="color: #a31515">"_data"] == <span style="color: blue">null)
{
Cache[<span style="color: #a31515">"_data"] = <span style="color: blue">value;
}
}
}

<span style="color: blue">#endregion

片段2:绑定Repeater

<pre class="code"><span style="color: blue">#region Private Methods

<span style="color: gray">///


/// <span style="color: green">绑定Repeater
<span style="color: gray">///

<span style="color: blue">private void BindRepeater()
{
<span style="color: blue">if (DataSource == <span style="color: blue">null)
{
<span style="color: #2b91af">IList<<span style="color: #2b91af">Book> books = BookRepository.GetAll().ToList();
DataSource = books;
}

<span style="color: green"&gt;// 首次加载时绑定数据源
</span><span style="color: blue"&gt;if</span>(ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>] == <span style="color: blue"&gt;null</span>)
{
    <span style="color: blue"&gt;this</span>.Repeater1.DataSource = DataSource;
    <span style="color: blue"&gt;this</span>.Repeater1.DataBind();
}

}

<span style="color: blue">#endregion

片段3:排序设置

<pre class="code"><span style="color: gray">///


/// <span style="color: green">设置排序字段、排序方式、排序文本
<span style="color: gray">///

<span style="color: blue">private void SetSorting(<span style="color: #2b91af">RepeaterCommandEventArgs e)
{
<span style="color: blue">var sort = (<span style="color: #2b91af">LinkButton)e.Item.FindControl(e.CommandName.Trim());
<span style="color: blue">if (e.Item.ItemType == <span style="color: #2b91af">ListItemType.Header)
{
<span style="color: blue">string sortText = <span style="color: blue">string.Empty;

    <span style="color: green"&gt;// 存储排序字段、排序方式、排序文本
    </span><span style="color: blue"&gt;if </span>(ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>] == <span style="color: blue"&gt;null </span>|| ViewState[<span style="color: #a31515"&gt;"SortBy"</span>].ToString() != e.CommandName)
    {
        ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>] = <span style="color: #a31515"&gt;"ASC"</span>;
        ViewState[<span style="color: #a31515"&gt;"SortBy"</span>] = e.CommandName;
        sortText = sort.Text + <span style="color: #a31515"&gt;"▲"</span>;
    }
    <span style="color: blue"&gt;else
    </span>{
        ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>] = ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>].ToString() == <span style="color: #a31515"&gt;"ASC" </span>? <span style="color: #a31515"&gt;"DESC" </span>: <span style="color: #a31515"&gt;"ASC"</span>;

        <span style="color: green"&gt;// 排序时更改文本
        </span><span style="color: blue"&gt;if </span>(sort.Text.IndexOf(<span style="color: #a31515"&gt;"▲"</span>) == -1)
        {
            <span style="color: blue"&gt;if </span>(sort.Text.IndexOf(<span style="color: #a31515"&gt;"▼"</span>) == -1)
                sortText = sort.Text + <span style="color: #a31515"&gt;"▲"</span>;
            <span style="color: blue"&gt;else
                </span>sortText = sort.Text.Replace(<span style="color: #a31515"&gt;"▼"</span>,<span style="color: #a31515"&gt;"▲"</span>);
        }
        <span style="color: blue"&gt;else
        </span>{
            sortText = sort.Text.Replace(<span style="color: #a31515"&gt;"▲"</span>,<span style="color: #a31515"&gt;"▼"</span>);
        }
    }
    ViewState[<span style="color: #a31515"&gt;"SortText"</span>] = sortText;
}

}

片段4:前端数据源解析

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

<a name="a1">

2. 传统排序方式

在线Demo浏览:

<pre class="code"><span style="color: blue">protected void Repeater1_ItemCommand(<span style="color: blue">object source,<span style="color: #2b91af">RepeaterCommandEventArgs e)
{
<span style="color: green">// 设置排序
SetSorting(e);

<span style="color: blue"&gt;if </span>(ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>] != <span style="color: blue"&gt;null</span>)
{
    <span style="color: blue"&gt;string </span>sortOrder = ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>].ToString();
    <span style="color: blue"&gt;switch </span>(ViewState[<span style="color: #a31515"&gt;"SortBy"</span>].ToString())
    {
        <span style="color: blue"&gt;case </span><span style="color: #a31515"&gt;"ISBN"</span>:
            Repeater1.DataSource = sortOrder == <span style="color: #a31515"&gt;"ASC"
                                        </span>? DataSource.OrderBy(b => b.ISBN)
                                        : DataSource.OrderByDescending(b => b.ISBN);
            <span style="color: blue"&gt;break</span>;
        <span style="color: blue"&gt;case </span><span style="color: #a31515"&gt;"Title"</span>:
            Repeater1.DataSource = sortOrder == <span style="color: #a31515"&gt;"ASC"
                                        </span>? DataSource.OrderBy(b => b.Title)
                                        : DataSource.OrderByDescending(b => b.Title);
            <span style="color: blue"&gt;break</span>;
        <span style="color: blue"&gt;case </span><span style="color: #a31515"&gt;"Category"</span>:
            Repeater1.DataSource = sortOrder == <span style="color: #a31515"&gt;"ASC"
                                        </span>? DataSource.OrderBy(b => b.CategoryName)
                                        : DataSource.OrderByDescending(b => b.CategoryName);
            <span style="color: blue"&gt;break</span>;
        <span style="color: blue"&gt;case </span><span style="color: #a31515"&gt;"Author"</span>:
            Repeater1.DataSource = sortOrder == <span style="color: #a31515"&gt;"ASC"
                                        </span>? DataSource.OrderBy(b => b.Author)
                                        : DataSource.OrderByDescending(b => b.Author);
            <span style="color: blue"&gt;break</span>;
        <span style="color: blue"&gt;case </span><span style="color: #a31515"&gt;"Package"</span>:
            Repeater1.DataSource = sortOrder == <span style="color: #a31515"&gt;"ASC"
                                        </span>? DataSource.OrderBy(b => b.Package)
                                        : DataSource.OrderByDescending(b => b.Package);
            <span style="color: blue"&gt;break</span>;
        <span style="color: blue"&gt;case </span><span style="color: #a31515"&gt;"Pages"</span>:
            Repeater1.DataSource = sortOrder == <span style="color: #a31515"&gt;"ASC"
                                        </span>? DataSource.OrderBy(b => b.Pages)
                                        : DataSource.OrderByDescending(b => b.Pages);
            <span style="color: blue"&gt;break</span>;
    }
    Repeater1.DataBind();
}

}?

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

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

在线Demo:

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

<pre class="code"><span style="color: blue">protected void Repeater1_ItemCommand(<span style="color: blue">object source,<span style="color: #2b91af">RepeaterCommandEventArgs e)
{
<span style="color: green">// 设置排序
SetSorting(e);

<span style="color: blue"&gt;if </span>(ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>] != <span style="color: blue"&gt;null</span>)
{
    Repeater1.DataSource = ViewState[<span style="color: #a31515"&gt;"SortOrder"</span>].ToString() == <span style="color: #a31515"&gt;"ASC"
                                </span>? DataSource.OrderBy(
                                    o => <span style="color: #2b91af"&gt;TypeHelper</span>.GetPropertyValue(o,ViewState[<span style="color: #a31515"&gt;"SortBy"</span>].ToString()))
                                : DataSource.OrderByDescending(
                                    o => <span style="color: #2b91af"&gt;TypeHelper</span>.GetPropertyValue(o,ViewState[<span style="color: #a31515"&gt;"SortBy"</span>].ToString()));
    Repeater1.DataBind();
}

}

Type类代码:

<pre class="code"><span style="color: blue">public static class <span style="color: #2b91af">TypeHelper
{
<span style="color: blue">public static object GetPropertyValue(<span style="color: blue">object obj,<span style="color: blue">string name)
{
<span style="color: blue">return obj == <span style="color: blue">null ? <span style="color: blue">null : obj.GetType()
.GetProperty(name)
.GetValue(obj,<span style="color: blue">null);
}
}
<a name="a3">

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

在线Demo:

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

<pre class="code">Repeater1.DataSource = DataSource.<font style="background-color: #ffff00" color="#ff0000">OrderBy(e.CommandName).ToList();

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

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

在项目下添加一个LinqExtension类:

<pre class="code"><span style="color: blue">public static class <span style="color: #2b91af">LinqExtension
{
<span style="color: blue">public static <span style="color: #2b91af">IEnumerable Sort(<span style="color: blue">this <span style="color: #2b91af">IEnumerable source,<span style="color: blue">string sortExpression)
{
<span style="color: blue">string[] sortParts = sortExpression.Split(<span style="color: #a31515">' ');
<span style="color: blue">var param = <span style="color: #2b91af">Expression.Parameter(<span style="color: blue">typeof (T),<span style="color: blue">string.Empty);
<span style="color: blue">try
{
<span style="color: blue">var property = <span style="color: #2b91af">Expression.Property(param,sortParts[0]);
<span style="color: blue">var sortLambda = <span style="color: #2b91af">Expression.Lambda<<span style="color: #2b91af">Func<T,<span style="color: blue">object>>(<span style="color: #2b91af">Expression.Convert(property,<span style="color: blue">typeof (<span style="color: blue">object)),param);

        <span style="color: blue"&gt;if </span>(sortParts.Length > 1 &amp;&amp; sortParts[1].Equals(<span style="color: #a31515"&gt;"desc"</span>,<span style="color: #2b91af"&gt;StringComparison</span>.OrdinalIgnoreCase))
        {
            <span style="color: blue"&gt;return </span>source.AsQueryable<T>().OrderByDescending<T,<span style="color: blue"&gt;object</span>>(sortLambda);
        }
        <span style="color: blue"&gt;return </span>source.AsQueryable<T>().OrderBy<T,<span style="color: blue"&gt;object</span>>(sortLambda);
    }
    <span style="color: blue"&gt;catch </span>(<span style="color: #2b91af"&gt;ArgumentException</span>)
    {
        <span style="color: blue"&gt;return </span>source;
    }
}

}

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

<pre class="code"><span style="color: blue">protected void Repeater1_ItemCommand(<span style="color: blue">object source,<span style="color: #2b91af">RepeaterCommandEventArgs e)
{
<span style="color: green">// 设置排序
SetSorting(e);
<span style="color: blue">if (ViewState[<span style="color: #a31515">"SortOrder"] != <span style="color: blue">null)
{
Repeater1.DataSource = DataSource.Sort(<span style="color: blue">string.Concat(e.CommandName,<span style="color: #a31515">" ",ViewState[<span style="color: #a31515">"SortOrder"].ToString()));
Repeater1.DataBind();
}
}

5. 总结

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

一个很小的功能可以有很多方式去实现,选择最高效最简便的方式是我们努力的方向,正如文章开头提供的3个Demo一样,它们的结果一模一样,但后面的实现方式却各不相同。一个粗俗的比喻:最开始我们给自己的代码穿上了很多衣服,甚至棉衣也穿上了,但是夏天快到了,天气较热,又是在家里,我只想为代码穿一条内裤,即使内裤里面可能筛了很多东西,但是我看到的就是一条内裤。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读