使用单个链接对字段进行升序和降序排序

时间:2015-11-19 15:42:57

标签: asp.net-mvc linq sorting asp.net-mvc-5

所以我有一个带有表格的MVC应用程序,当点击标题时,我希望它根据点击的次数以升序或降序排序。

目前我只能按降序或升序排序我不知道如何实施两者。 userName只是我在用户登录时从其他控制器获取的变量,并且我正在使用交换机,因为我计划使用多个可以排序的标头。

查看

<table>
    <tr>
        <th>
            <a href="@Url.Action("Dispatch", "Calls", new { userName = Session["UserName"], new { sortOrder = "Name_desc" })">Name</a>
        </th>
    </tr>
</table>

控制器

public ActionResult Index(string userName, string sortOrder)
{
    string userName = Session["UserName"].ToString();

    var model = from t in db.Users
                where t.UserName == userName
                select t;

    switch(sortOrder)
    {
        case "Name_desc":
            model = model.OrderByDescending(t => t.UserName);
            break;
    }
}

4 个答案:

答案 0 :(得分:9)

将您的排序顺序放在ViewBag值中。内联检查(Viewbag.NameSort):

查看:

<th>
    <a href="@Url.Action("Dispatch", "Calls", new { userName = Session["UserName"], new { sortOrder = ViewBag.NameSort })">Name</a>
</th>

控制器:

public ActionResult Index(string userName, string sortOrder)
{
    string userName = Session["UserName"].ToString();

    // Convert sort order
    ViewBag.NameSort = sortOrder == "Name" ? "Name_desc" : "Name";

    var model = from t in db.Users
                where t.UserName == userName
                select t;

    switch(sortOrder)
    {
        case "Name_desc":
            model = model.OrderByDescending(t => t.UserName);
            break;
        case "Name":
            model = modelOrderBy(t => t.UserName);
            break;
    }
}

答案 1 :(得分:2)

我不想使用ViewBag值,因此我使用隐藏元素的属性来跟踪用户排序选择。

我有一个带有内部局部视图的Home Index页面,该页面显示用户活动日志表。该表有一个标题行,在大多数列中有一个下拉列表和一个右对齐排序图标。当用户单击排序图标时,数据按该列按升序或降序排序(取决于排序切换状态)。

我会事先道歉,我已经为这个简单的解决方案补充了这么多代码,但我认为这个人(可能是新手)看完我的答案,代码的完整上下文补充应该有助于在不使用ViewBags的情况下整合简单但完整的数据检索和排序切换解决方案。

帖子底部的代码使用说明。

我的索引视图(隐藏元素所在的位置)。 sort属性是这里的主要关注点:

<div class="hidden">
    <span id="act-user-sort" sort=""></span>
    <span id="act-type-sort" sort=""></span>
    <span id="act-level-sort" sort=""></span>
    <span id="act-date-sort" sort=""></span>
</div>
<section id="partial_Activity">
    @Html.Action("_Activity", "Home")
</section>

ActionResult“_Activity”最初将_Activity局部视图返回到上面的索引视图中:

public ActionResult _Activity()
{
    using (var context = new ApplicationDbContext())
    {
        //create new LogModel object.  this holds all that will be returned to the view
        LogModel logModel = new LogModel();

        //create new LogSelect object. this is the list of drop downs for the activity log table.
        LogSelect logSelect = new LogSelect();

        //query to get initial set
        var result = from log in context.Logs
                     join user in context.Users on log.UserId equals user.Id into userlog
                     from user in userlog.DefaultIfEmpty()
                     orderby log.LogDate descending
                     select new Models.UserActivity { Log = log, User = user }; //this could bring back null user objects

        //populate items for drop down lists
        logSelect.LogUsers = result.Select(u => new LogUser { Name = u.User.FirstName + " " + u.User.LastName, Id = u.User.Id }).Distinct().ToList();
        logSelect.LogTypes = result.Select(t => t.Log.Type).Distinct().ToList();
        logSelect.LogLevels = result.Select(t => t.Log.Level).Distinct().ToList();

        //initial page for pagination is 1, default page size is 10.
        int pageIndex = 1;
        int pageSize = 10;

        //return view with paginated list.
        PaginatedList<UserActivity> pgList = PaginatedList<UserActivity>.Create(result.AsNoTracking(), pageIndex, pageSize);

        //fill view model.
        logModel.LogSelect = logSelect;
        logModel.UserActivity = pgList;

        return PartialView(logModel);
    }
}

我的“_Activity”行动 局部视图内部(表和排序按钮所在的位置):

@model Utils.Models.LogModel
<style>
...
</style>
<div>
    <h3>Recent Activity</h3>
</div>
<div style="height:20px"></div>
@* the panel class rounds the corners of the table *@
<div class="panel panel-default table-responsive" style="font-size:.9em;">
    <table id="log-table" class="table table-striped table-bordered table-hover log-table" style="width:100%;">
        <thead>
            <tr class="bg-primary">
                <th class="dropdown log-dropdown">
                    <a href="#" data-toggle="dropdown" class="dropdown-toggle">User&nbsp;&nbsp;<b class="caret"></b></a>
                    <div class="log-dropdown-sort log-dropdown-sort-init">
                        <a sort="" href="#" id="log-dropdown-user-sort"><img src="~/Images/ui/alpha-sort-white.png" /></a>
                    </div>
                    <ul id="log-dropdown-user" class="dropdown-menu log-dropdown">
                        @foreach (var user in Model.LogSelect.LogUsers)
                        {
                            <li><a id="log-user" href="#">@user.Name</a><span id="log-user-id" class="hidden">@user.Id</span></li>
                        }
                    </ul>
                </th>
                <th>Action</th>
                <th class="dropdown log-dropdown">
                    <a href="#" data-toggle="dropdown" class="dropdown-toggle">Type&nbsp;&nbsp;<b class="caret"></b></a>
                    <div class="log-dropdown-sort log-dropdown-sort-init">
                        <a sort="" href="#" id="log-dropdown-type-sort"><img src="~/Images/ui/alpha-sort-white.png" /></a>
                    </div>
                    <ul id="log-dropdown-type" class="dropdown-menu">
                        @foreach (var log in Model.LogSelect.LogTypes)
                        {
                            <li><a id="log-type" href="#">@log</a><span class="hidden">@log</span></li>
                        }
                    </ul>
                </th>
                <th class="log-dropdown">
                    Date
                    <div class="log-dropdown-sort log-dropdown-sort-init">
                        <a sort="" href="#" id="log-dropdown-date-sort"><img src="~/Images/ui/alpha-sort-white.png" /></a>
                    </div>
                    <div class="log-dropdown-date log-dropdown-date-init">
                        <a href="#" id="log-dropdown-date-range"><img src="~/Images/ui/calendar-white.png" /></a>
                    </div>
                </th>
            </tr>
        </thead>
        <tbody>

            @foreach (var log in Model.UserActivity)
            {
                <tr>
                    <td>@log.User.FirstName @log.User.LastName</td>
                    <td class="log-message">@log.Log.Message</td>
                    <td>@log.Log.Type</td>
                    <td class="log-date">@log.Log.LogDate</td>
                </tr>
            }
        </tbody>
    </table>

</div>
<div>
    <ul class="pagination">
        <li>
            <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
        @for (int pg = 1; pg <= Model.UserActivity.TotalPages; pg++)
        {
            if (pg == Model.UserActivity.PageIndex)
            {
                <li class="active"><a href="#">@pg</a></li>
            }
            else
            {
                <li><a href="#">@pg</a></li>
            }
        }
        <li>
            <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    </ul>
</div>

处理事件的jquery:

/**********************************************************************************************
_Activity.cshtml

/*********************************************************************************************/

//activity log sort buttons.
$('#partial_Activity').on('click', '#log-dropdown-user-sort', function (e) {
    e.preventDefault();
    var data = {};
    data.sortOrder = setSort($("#act-user-sort"), "user");
    GetActivity(data);
});

$('#partial_Activity').on('click', '#log-dropdown-type-sort', function (e) {
    e.preventDefault();
    var data = {};
    data.sortOrder = setSort($("#act-type-sort"), "type");
    GetActivity(data);
});

$('#partial_Activity').on('click', '#log-dropdown-level-sort', function (e) {
    e.preventDefault();
    var data = {};
    data.sortOrder = setSort($("#act-level-sort"), "level");
    GetActivity(data);
});

$('#partial_Activity').on('click', '#log-dropdown-date-sort', function (e) {
    e.preventDefault();
    var data = {};
    data.sortOrder = setSort($("#act-date-sort"), "date");
    GetActivity(data);
});


//this function checks and sets the "sort" attribute of the passed element.
//then based on setting of the "sort" attribute, returns a string value that will be used by code-behind to sort values in the table.
function setSort(element, sort) {

    if (element.attr("sort") == "") {
        element.attr("sort", "asc");
        sort = sort + "_asc";
    }
    else {
        if (element.attr("sort") == "asc") {
            element.attr("sort", "desc")
            sort = sort + "_desc";
        }
        else {
            element.attr("sort", "asc")
            sort = sort + "_asc";
        }
    }
    return sort;
}

function GetActivity(options) {
    $.ajax({
        cache: false,
        type: "GET",
        url: "../Home/GetActivity",
        data: options,
        contentType: "application/json; charset=utf-8",
        success: function (obj) {
            $("#partial_Activity").html(obj);
        }
    }).done(function () {
    });
}

当用户单击排序按钮时返回部分视图的GET方法:

[HttpGet]
public PartialViewResult GetActivity(
    string sortOrder,
    string userFilter,
    string typeFilter,
    string levelFilter,
    DateTime? startDate,
    DateTime? endDate,
    int pageIndex = 1,
    int pageSize = 10)
{

    using (var context = new ApplicationDbContext())
    {
        //create new LogModel object.  this holds all that will be returned to the view
        LogModel logModel = new LogModel();

        //create new LogSelect object. this is the list of drop downs for the activity log table.
        LogSelect logSelect = new LogSelect();

        //query
        var result = from log in context.Logs
                     join user in context.Users on log.UserId equals user.Id into userlog
                     from user in userlog.DefaultIfEmpty()
                     orderby log.LogDate descending
                     select new Models.UserActivity { Log = log, User = user }; //this could bring back null user objects.

        //populate items for drop down lists
        logSelect.LogUsers = result.Select(u => new LogUser { Name = u.User.FirstName + " " + u.User.LastName, Id = u.User.Id }).Distinct().ToList();
        logSelect.LogTypes = result.Select(t => t.Log.Type).Distinct().ToList();
        logSelect.LogLevels = result.Select(t => t.Log.Level).Distinct().ToList();

        //filters
        if (!String.IsNullOrEmpty(userFilter)) { result = result.Where(r => r.User.UserName.Equals(userFilter)); }
        if (!String.IsNullOrEmpty(typeFilter)) { result = result.Where(r => r.Log.Type.Equals(typeFilter)); }
        if (!String.IsNullOrEmpty(levelFilter)) { result = result.Where(r => r.Log.Level.Equals(levelFilter)); }
        if (startDate.HasValue) { result = result.Where(r => r.Log.LogDate >= startDate); }
        if (endDate.HasValue) { result = result.Where(r => r.Log.LogDate <= endDate); }

            //always default sorting by date desc
            result = result.OrderByDescending(r => r.Log.LogDate);

            //sorting (any selection other than date sorting will be sorted secondarily by date descending)
            switch (sortOrder)
            {
                case "date_asc":
                    result = result.OrderBy(r => r.Log.LogDate);
                    break;
                case "date_desc":
                    result = result.OrderByDescending(r => r.Log.LogDate);
                    break;
                case "user_asc":
                    result = result.OrderBy(r => r.User.FirstName)
                                   .ThenByDescending(r => r.Log.LogDate);
                    break;
                case "user_desc":
                    result = result.OrderByDescending(r => r.User.FirstName)
                                   .ThenByDescending(r => r.Log.LogDate);
                    break;
                case "type_asc":
                    result = result.OrderBy(r => r.Log.Type)
                                   .ThenByDescending(r => r.Log.LogDate);
                    break;
                case "type_desc":
                    result = result.OrderByDescending(r => r.Log.Type)
                                   .ThenByDescending(r => r.Log.LogDate);
                    break;
                case "level_asc":
                    result = result.OrderBy(r => r.Log.Level)
                                   .ThenByDescending(r => r.Log.LogDate);
                    break;
                case "level_desc":
                    result = result.OrderByDescending(r => r.Log.Level)
                                   .ThenByDescending(r => r.Log.LogDate);
                    break;
                default:
                    break;
            }

        //turn result into paginated list
        PaginatedList<UserActivity> pgList = PaginatedList<UserActivity>.Create(result.AsNoTracking(), pageIndex, pageSize);

        //fill view model.
        logModel.LogSelect = logSelect;
        logModel.UserActivity = pgList;

        //return model to the view
        return PartialView("_Activity", logModel);
    }
}

说明:

当您点击<a id="log-dropdown-user-sort"><img.../></a>局部视图中的_Activity时,javascript点击事件$('#partial_Activity').on('click', '#log-dropdown-user-sort', function (e) {}会触发并调用setSort(DOM element, string)功能。

setSort()函数设置传递元素的"sort"属性,在'asc''desc'之间切换属性值,从而影响函数中的未来逻辑流,并返回连接字符串值,将用作sortOrder GET方法中的GetActivity参数,该方法将在下一个方法中调用。

然后GetActivity GET方法查询并返回基于sortOrder语句评估的switch参数排序的数据。

答案 2 :(得分:0)

只需在您的.js文件中放置代码-“订单”:[[6,“ asc”]]。其中6代表列的placeNumber。例如1.id,2.name。等

答案 3 :(得分:0)

对于Razor页面,我只是在页面模型中添加了if-else语句以及“ CurrentSortDir”变量和“ ToggleSortDir”变量。

所以我的“ index.cshtml”:

         <th>
            <a asp-page="./Index" 
            asp-route-sortOrder="ManufacturerPN"
            asp-route-sortDir = "@Model.ToggleSortDir">
                @Html.DisplayNameFor(model => model.Inventory[0].ManufacturerPN)
            </a>
          </th>

还有我的index.cshtml.cs:

public string CurrentSortDir { get; set; }
public string ToggleSortDir {get; set; }
public async Task OnGetAsync(string sortOrder, string sortDir, string currentFilter, string searchString, int? pageIndex)
    {
        CurrentSort = sortOrder;
        CurrentSortDir = sortDir;
  if (CurrentSortDir == "DESC")
        {
            ToggleSortDir = "ASC";
            switch (sortOrder)
            {
                case "ManufacturerPN":
                    Items = Items.OrderByDescending(s => s.ManufacturerPN);
                    break;
             ....
             }
         }
         else
         {
           ToggleSortDir = "DESC";
            switch (sortOrder)
            {
                case "ManufacturerPN":
                    Items = Items.OrderBy(s => s.ManufacturerPN);
                    break;
               ....
             }
           }

您最终将获得一个全局排序方向...但是我认为这还可以。否则,您将需要为每个列使用单独的var,然后在每种情况下都添加。