在 asp.net MVC 中对表进行排序
Posted
技术标签:
【中文标题】在 asp.net MVC 中对表进行排序【英文标题】:Sorting a table in asp.net MVC 【发布时间】:2011-01-03 04:20:14 【问题描述】:我想知道人们是如何在 asp.net mvc 中对表格进行排序的? 我听说过适用于非分页表的 javascript 解决方案,例如 jquery 的表格排序器,但我需要一个适用于分页表的解决方案。
我正在做的项目目前使用以下解决方案,但我发现它非常混乱。
控制器
public ActionResult Sort(string parameter)
IEnumerable<IProduct> list;
if (Session["Model"] != null)
list = (IEnumerable<IProduct>)Session["Model"]).ToList<IProduct>();
else
list = _service.GetAll();
if (Session["parameter"] == null && Session["sortDirection"] == null)
//set the parameter and set the sort to desc
Session["parameter"] = parameter;
Session["sortDirection"] = "DESC";
else if (Session["parameter"] != null) //already set so not the first time
//same parameter sent
if (Session["parameter"].ToString().Equals(parameter))
//check sort direction and reverse
if (Session["sortDirection"].ToString().Equals("DESC"))
Session["sortDirection"] = "ASC";
else
Session["sortDirection"] = "DESC";
else //different parameter sent
Session["sortDirection"] = "DESC";
Session["parameter"] = parameter;
if (Session["sortDirection"].CompareTo("ASC") == 0)
list = Models.ContollerHelpers.SortingHelper.OrderBy(list.AsQueryable(), column);
else
list = Models.ContollerHelpers.SortingHelper.OrderByDescending(list.AsQueryable(), column);
return View("Results", list.ToList);
助手
public class Helper()
private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
ParameterExpression param = Expression.Parameter(typeof(T), string.Empty); // I don't care about some naming
MemberExpression property = Expression.PropertyOrField(param, propertyName);
LambdaExpression sort = Expression.Lambda(property, param);
MethodCallExpression call = Expression.Call(
typeof(Queryable),
(!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
new[] typeof(T), property.Type ,
source.Expression,
Expression.Quote(sort));
return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call);
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
return OrderingHelper(source, propertyName, false, false);
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
return OrderingHelper(source, propertyName, true, false);
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string propertyName)
return OrderingHelper(source, propertyName, false, true);
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string propertyName)
return OrderingHelper(source, propertyName, true, true);
列表视图
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Models.Interface.IProduct>>" %>
<% Session["model"] = Model; %>
<table>
<tr>
<th>
Edit Details
</th>
<th>
<%=html.ActionLink("Id","Sort",new parameter ="Id") %>
</th>
<th>
<%=Html.ActionLink("Name", "Sort", new parameter = "Name")%>
</th>
<th>
<%=Html.ActionLink("Status", "Sort", new parameter = "Status" )%>
</th>
<th>
<%=Html.ActionLink("Notes", "Sort", new parameter = "Notes")%>
</th>
</tr>
<% foreach (var item in Model) %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new id=item.Id ) %> |
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td>
<%= Html.Encode(item.Status) %>
</td>
<td>
<%= Html.Encode(item.Notes) %>
</td>
</tr>
<% %>
</table>
这是做这种事情的唯一方法吗? 如果有人知道不涉及将所有记录一次加载到页面的更好方法,请链接到示例。
【问题讨论】:
@AlteredConcept q 太宽泛了,因为你并没有说你最关心的是什么。是视图(几乎没有,因为它非常简单),使用 linq 以通用方式排序的方式,使用 session 来保存参数,使用类似的“参数”或其解析。 很抱歉。控制器是最困扰我的。我不想在每个控制器中为每个实体列表视图重复所有这些代码。这是很多重复的代码。我试图找出一种可以将其放置在基本控制器中的方法,但运行的是空白。所以我想看看其他人是否有更好更优雅的排序方法 嗯?为什么你的头疼? 【参考方案1】:查看 DataTables @ DataTables 这将让您对结果进行分页并通过简单的设置进行查询。它适用于 ajax 和 json 数据。看看样品。希望对您有所帮助。
【讨论】:
+1。我已成功在 ASP.NET MVC 应用程序中使用 DataTables jQuery 插件和服务器端处理 (datatables.net/usage/server-side)。 这会在加载时将所有数据加载到页面上(即使它在加载后对数据进行分页)。尝试一次加载 1000 多条记录。页面显示需要一段时间。 使用服务器端处理只发送显示给客户端datatables.net/usage/server-side的行,正如 Anton 指出的那样。 您也可以将其与 PartialView 和返回 JsonResult 的控制器结合使用 你能发布一个如何做到这一点的示例@chris 吗?【参考方案2】:尝试以下扩展方法(从头开始):
static class OrderByExtender
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, string key, string direction)
LambdaExpression sortLambda = BuildLambda<T>(key);
if(direction.ToUpper() == "ASC")
return collection.OrderBy((Func<T, object>)sortLambda.Compile());
else
return collection.OrderByDescending((Func<T, object>)sortLambda.Compile());
public static IOrderedEnumerable<T> ThenBy<T>(this IOrderedEnumerable<T> collection, string key, string direction)
LambdaExpression sortLambda = BuildLambda<T>(key);
if (direction.ToUpper() == "ASC")
return collection.ThenBy((Func<T, object>)sortLambda.Compile());
else
return collection.ThenByDescending((Func<T, object>)sortLambda.Compile());
private static LambdaExpression BuildLambda<T>(string key)
ParameterExpression TParameterExpression = Expression.Parameter(typeof(T), "p");
LambdaExpression sortLambda = Expression.Lambda(Expression.Convert(Expression.Property(TParameterExpression, key), typeof(object)), TParameterExpression);
return sortLambda;
用法:
var products = Session["Model"] as IEnumerable<Product>() ?? _service.GetAll();
return products.OrderBy("Name", "ASC").ThenBy("Price", "DESC");
假设您一次只使用 1 个 orderby 条件,您可以使用:
var products = Session["Model"] as IEnumerable<Product>();
var sortDirection = Session["Direction"] as string ?? "DESC";
Session["Direction"] = sortDirection == "DESC" ? "ASC" : "DESC";
sortDirection = Session["Direction"] as string;
return products.OrderBy(parameter, sortDirection);
【讨论】:
direction.ToLower() 不应该是 direction.ToUpper() 吗? 正确。感谢您指出这一点,我在记事本中写了这些东西:-) 没问题。我喜欢这种方法,但我遇到了一些问题。有时它会正确排序,有时则不会(而不是升序,而是降序,反之亦然)。 在你的网址中添加一个参数order=DESC
/order=ASC
。然后在您的前端处理单击标题是否会导致 ASC/DESC 排序。然后你可以像public ActionResult Sort(string parameter, string order)
一样排序。【参考方案3】:
如果 JavaScript 被禁用,你就有问题了。
我会选择 noscript 解决方案。
我有两个单选按钮组:
direction: ( ) ascending (.) descending
orderBy: (.) Id ( ) Name ( ) Status
我会将 View 视为具有多个提交按钮的 表单:
(不带 JavaScript)~~ 两个按钮的名称相同。
在您的 .aspx 页面上,添加三个按钮:
<input type="submit" value="Requery" name="submitButton"/>
<input type="submit" value="Previous" name="submitButton"/>
<input type="submit" value="Next" name="submitButton"/>
在您的控制器中:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Sort(string direction, string orderBy, string submitButton)
if (submitButton == "Requery") //et cetera
TMTOWTDI: 方法不止一种
【讨论】:
【参考方案4】:我更喜欢这里描述的方法: http://www.c-sharpcorner.com/UploadFile/camurphy/csharpLists03302006170209PM/csharpLists.aspx
所以例如:
var products = new List<Products>();
products = ProductRepository.GetAll();
// Sort Results
products.Sort(
delegate(Products p1, Products p2)
return p1.Name.CompareTo(p2.Name);
);
【讨论】:
你不是说p1.Name.CompareTo(p2.Name)
吗?【参考方案5】:
非常喜欢 Jan 的解决方案 - 非常感谢 Jan... 您刚刚为我节省了大约 60 行代码,其中包含解析每个列标题的 case 语句。当与两个会话变量一起使用时,该解决方案“可以进行出色的切换单击,仅按表上的 1 列解决方案排序”,一个用于将 ASC/DESC 保留为布尔值,另一个用于保存类型/列名称。
今天下午我使用了这个 C# 示例扩展并用 VB 实现了它。我设法将一个 30 行的 case 语句缩减为一行代码。
在风景中:
<th>Date <a class="clickable" href="<%=Url.Action("SortStationVisits", New With .SortField = "PlanningDate")%>"><span class="colSort" style="display: inline-table;"></span></a></th>
扩展(公共模块 OrderByExtender):
Imports System.Linq.Expressions
Public Function OrderBy(Of T)(collection As IEnumerable(Of T), key As String, isDescending As Boolean) As IOrderedEnumerable(Of T)
Dim sortLambda As LambdaExpression = BuildLambda(Of T)(key)
If isDescending Then
Return collection.OrderByDescending(DirectCast(sortLambda.Compile(), Func(Of T, Object)))
Else
Return collection.OrderBy(DirectCast(sortLambda.Compile(), Func(Of T, Object)))
End If
End Function
Public Function ThenBy(Of T)(collection As IOrderedEnumerable(Of T), key As String, isDescending As Boolean) As IOrderedEnumerable(Of T)
Dim sortLambda As LambdaExpression = BuildLambda(Of T)(key)
If (isDescending) Then
Return collection.ThenByDescending(DirectCast(sortLambda.Compile(), Func(Of T, Object)))
Else
Return collection.ThenBy(DirectCast(sortLambda.Compile(), Func(Of T, Object)))
End If
End Function
Private Function BuildLambda(Of T)(key As String) As LambdaExpression
Dim TParameterExpression As ParameterExpression = Expression.Parameter(GetType(T), "p")
Dim sortLambda As LambdaExpression = Expression.Lambda(Expression.Convert(Expression.[Property](TParameterExpression, key), GetType(Object)), TParameterExpression)
Return sortLambda
End Function
在控制器操作时:
Public Function SortStationVisits(Optional page As Integer = 1, Optional SortField As String = "") As ActionResult
Dim sps = LoadSession()
If SortField = sps.StationVisitSorter Then
sps.StationVisitDescOrder = Not (sps.StationVisitDescOrder)
Else
sps.StationVisitDescOrder = False
End If
sps.StationVisitSorter = SortField
SaveSession(sps)
Return RedirectToAction("Show")
End Function
在控制器展示方法(1行代码W00T!):
spv.SelectableStationVisits = spv.SelectableStationVisits.OrderBy(sps.StationVisitSorter, sps.StationVisitDescOrder).ToList
【讨论】:
以上是关于在 asp.net MVC 中对表进行排序的主要内容,如果未能解决你的问题,请参考以下文章
使用 ASP.Net 在 SQL 中对表的列值求和时出现异常
在 asp.net mvc 中对控制器进行简单的 Ajax 调用