【问题标题】:Mvc Asp Sorting itemsMvc Asp 排序项目
【发布时间】:2016-02-17 11:28:16
【问题描述】:

我在我的应用程序中使用 PagedList.MVC 进行分页。这工作正常。分页工作正常,OrderBy 下拉列表工作正常。当我从下拉列表中选择值时,它会给出所需的排序结果。我的意思是,如果我选择 A-Z,那么它会按升序对项目进行排序,但是当我单击第二页或下一页时,它不会对任何项目进行排序,并且 url 会变成这样

http://localhost:41213/Home/Products?page=2&pageSize=6

还有我怎样才能使这个 pageSize=6 成为动态的?我希望将其放入 {5,10,15,20} 之类的下拉列表中,当用户选择一个值时,它应该显示所选的项目数。

控制器

    [HttpGet]
    public ActionResult Products(int? OrderBy, int page=1, int pageSize=6)
    {
        private Shopping db = new Shopping();
        switch (OrderBy)
        {
            case 1:
                List<Product> listProductsasc = db.Products.OrderBy(p => p.Name).ToList();
                PagedList<Product> modelasc = new PagedList<Product>(listProductsasc, page, pageSize);
                return View(modelasc);
            case 2:
                List<Product> listProductsdesc = db.Products.OrderByDescending(p => p.Name).ToList();
                PagedList<Product> modeldesc = new PagedList<Product>(listProductsdesc, page, pageSize);
                return View(modeldesc);
            default:
                List<Product> listProducts = db.Products.ToList();
                PagedList<Product> modeldefault = new PagedList<Product>(listProducts, page, pageSize);
                return View(modeldefault);
        }
    }

查看

@model PagedList.IPagedList<FypStore.Models.Product>
@using PagedList.Mvc
<div class="row">
        <div class="col-sm-6">
            @using (Html.BeginForm("Products", "Home", FormMethod.Get, new { id = "Form1" }))
            {
                <div class="col-sm-8">
                    Sort by:
                    @Html.DropDownList("OrderBy", new List<SelectListItem>

                     {
                        new SelectListItem{ Text="A-Z", Value = "1" },
                        new SelectListItem{ Text="Z-A", Value = "2" }
                     }, "-- Order By --")

                </div>
                <div class="col-sm-4">
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <input type="submit" class="btn btn-default" value="Filter" />
                        </div>
                    </div>
                </div>
            }
        </div>
</div>
<br />

@Html.PagedListPager(Model, page => Url.Action("Products", new { page, pageSize = Model.PageSize }))
Showing @Model.FirstItemOnPage to @Model.LastItemOnPage of @Model.TotalItemCount Products

【问题讨论】:

  • 我在 URL 中没有看到 sort 参数,这意味着您的排序不会持续到下一页。尝试在 URL 中添加选定的排序值
  • 是的,如果我访问此网址localhost:41213/Home/…,那么它可以通过分页进行良好的排序。但是我怎样才能通过 OrderBy 选定的值?
  • 修改路由参数为new { new { OrderBy = ViewBag.SortOrder, page, pageSize = Model.PageSize },在控制器中,在返回视图前添加ViewBag.SortOrder = OrderBy;。但如果视图模型具有您需要的所有属性,那就更好了。
  • @StephenMuecke 你的评论对我很有帮助!非常感谢!。我让它工作了。你能给我一个关于你所说的视图模型的例子吗?我是初学者

标签: c# asp.net asp.net-mvc asp.net-mvc-4


【解决方案1】:

需要修改PagedListPager()方法的路由参数,包含排序顺序的值,例如

@Html.PagedListPager(Model, page => Url.Action("Products", new { OrderBy = ViewBag.SortOrder, page, pageSize = Model.PageSize }))

然后在方法中,包含

ViewBag.SortOrder = OrderBy;

在您返回视图之前。然而,更好的方法是使用包含视图使用的属性的视图模型,这将解决您的代码的其他问题(例如,如果您选择 "Z-A" 选项并提交表单,当您返回它时,集合是已排序,但下拉菜单显示 "-- Order By --" 表示未排序。您查看模型应该是

public class ProductsVM
{
  [Display(Name = "Sort by:")]
  public int? OrderBy { get; set; }
  public IEnumerable<SelectListItem> OrderList { get; set; }
  public int Page { get; set; }
  public int PageSize { get; set; }
  PagedList<Product> Products { get; set; }
}

控制器方法是

[HttpGet]
public ActionResult Products(int? orderBy, int page=1, int pageSize=6)
{
  private Shopping db = new Shopping();
  IEnumerable<Product> products = db.Products; // not .ToList()
  if (orderBy == 1)
  {
    products = products.OrderBy(p => p.Name);
  }
  else if (orderBy == 2)
  {
    products = products.OrderByDescending(p => p.Name)
  }

  ProductsVM model = new ProductsVM
  {
    OrderBy = orderBy,
    OrderList = new List<SelectListItem>
    {
      new SelectListItem{ Text="A-Z", Value = "1" },
      new SelectListItem{ Text="Z-A", Value = "2" }
    },
    Page = page,
    PageSize = pageSize,
    Products = new PagedList<Product>(products, page, pageSize);
  };
  return View(model);
}

最后修改你的视图以使用视图模型

@model ProductsVM
....
@using (Html.BeginForm("Products", "Home", FormMethod.Get))
{
  @Html.LabelFor(m => m.OrderBy)
  @Html.DropDownListForFor(m => m.OrderBy, Model.OrderList, "-- Order By --")
  <input type="submit" class="btn btn-default" value="Filter" />
}

@Html.PagedListPager(Model.Products, page => Url.Action("Products", new { orderBy = Model.OrderBy, page, pageSize = Model.PageSize }))
Showing @Model.Products.FirstItemOnPage to @Model.Products.LastItemOnPage of @Model.Products.TotalItemCount Products

【讨论】:

  • 我已经这样做了,但我不知道为什么我在运行应用程序时会收到此错误:方法 'Skip' 仅支持 LINQ to Entities 中的排序输入。必须在方法“Skip”之前调用方法“OrderBy”。我的代码中没有 Skip 方法。我已经搜索过了,但找不到。
  • .Skip()PagedList 调用。抱歉,我只是复制了您的代码部分(您的代码也会出现该错误)。添加else { products = products.OrderBy(p =&gt; p.someroperty) }(可能是ID 属性)以便在调用PagedList之前获得有序集合
  • 当我转到localhost:41213/Home/…时它可以工作,但当我直接转到http://localhost:41213/Home/Products时它不工作
【解决方案2】:

要修复您的页面链接,您需要将OrderBy 参数传递给视图。最简单的方法是使用 ViewBag。 在您的控制器中:

[HttpGet]
public ActionResult Products(int? OrderBy, int page = 1, int pageSize = 2)
{
    ViewBag.OrderBy = OrderBy;
    ...

在你看来:

@Html.PagedListPager(Model, page => Url.Action("Products", new { page, pageSize = Model.PageSize, OrderBy = ViewBag.OrderBy }))

另一种方法是使用视图模型。创建一个名为 ProductsViewModel 的类并在控制器中填充其属性,如下所示:

List<Product> modelasc = new PagedList<Product>(listProductsasc, page, pageSize);
var viewModel = ProductsViewModel();
viewModel.Products = modelasc;
viewModel.OrderBy = OrderBy;
return View(viewModel);

并在视图中使用它们:

@model FypStore.Models.ProductsViewModel
...
@Html.PagedListPager(Model, page => Url.Action("Products", new { page, pageSize = Model.Products.PageSize, OrderBy = Model.OrderBy }))

还有我怎样才能使这个 pageSize=6 成为动态的?

您的操作方式与使用 OrderBy 参数相同:创建一个名称为 pageSize 的下拉列表:

<div class="col-sm-8">
    Page size:
    @Html.DropDownList("pageSize", new List<SelectListItem>

            {
            new SelectListItem{ Text="2", Value = "2" },
            new SelectListItem{ Text="3", Value = "3" }
            }, "-- Page Size --")

</div>

旁注:您可能希望删除控制器中查询的.ToList(); 部分并将其移至其他位置。因为现在您的代码从数据库中获取所有数据,然后对其进行排序并提取必要数量的产品。您应该始终在数据库端执行排序和分页逻辑,并仅获取您希望在当前页面上显示的那些产品。

【讨论】:

    猜你喜欢
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多