Сортировка таблицы в asp.net MVC - PullRequest
15 голосов
/ 09 января 2010

Мне было интересно, как люди собирались сортировать таблицы в 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);
}

Helper

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>

Это единственный способ сделать что-то подобное? Если кто-нибудь знает более приятный способ, который не предполагает одновременной загрузки всех записей на страницу, тогда, пожалуйста, дайте ссылку на примеры.

Ответы [ 5 ]

10 голосов
/ 09 января 2010

Проверьте DataTables @ DataTables Это позволит вам отобразить результаты и запросить их с простой настройкой. он хорошо работает с данными ajax и json. Посмотрите на образцы. Надеюсь, это поможет вам.

8 голосов
/ 13 января 2010

Попробуйте следующие методы расширения (от верха головы):

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 условие заказа за раз, вы можете использовать:

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);
4 голосов
/ 14 января 2010

Если JavaScript отключен, у вас есть проблема.

Я бы выбрал решение noscript .

У меня было бы две группы переключателей:

direction:  ( ) ascending    (.) descending

orderBy:  (.) Id   ( ) Name   ( ) Status

Я бы обработал Просмотр как форму с несколькими кнопками отправки:

(без 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 : есть больше, чем один способ сделать это

0 голосов
/ 24 апреля 2012

Определенно нравится Решение Яна - большое спасибо Ян ... Вы только что сохранили мне около 60 строк кода с оператором case, анализирующим каждый из заголовков столбцов. Решение «делает большой щелчок переключателем, сортировка только по 1 столбцу для таблиц», при использовании с двумя переменными сеанса, одна для сохранения ASC / DESC в качестве логического значения, а другая для хранения имени типа / столбца.

Я использовал это расширение примера C # и реализовал его с VB сегодня днем. Мне удалось сократить 30-строчный регистр в одну строку кода.

У ВИДА:

<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
0 голосов
/ 09 января 2010

Я предпочитаю методы, описанные здесь: 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);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...