[翻译][MVC 5 + EF 6] 3:排序、过滤、分页

 

原文:Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application

 

1.添加排序

1.1.修改Controllers\StudentController.cs的Index:

public ActionResult Index(string sortOrder)

{

   ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";

   ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

   var students = from s in db.Students

                  select s;

   switch (sortOrder)

   {

      case "name_desc":

         students = students.OrderByDescending(s => s.LastName);

         break;

      case "Date":

         students = students.OrderBy(s => s.EnrollmentDate);

         break;

      case "date_desc":

         students = students.OrderByDescending(s => s.EnrollmentDate);

         break;

      default:

         students = students.OrderBy(s => s.LastName);

         break;

   }

   return View(students.ToList());

}

1.2.修改Views\Student\Index.cshtml

<p>

    @Html.ActionLink("Create New", "Create")

</p>

<table>

    <tr>

        <th> @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm }) </th>

        <th>First Name </th>

        <th> @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm }) </th>

        <th></th>

    </tr>

  效果图:

Students_Index_page_with_sort_hyperlinks

2.添加搜索框

2.1.修改Controllers\StudentController.cs的Index:

        public ViewResult Index(string sortOrder, string searchString)

        {

            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";

            ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

            var students = from s in db.Students

                           select s;

            if (!String.IsNullOrEmpty(searchString)) { students = students.Where(s => s.LastName.Contains(searchString) || s.FirstMidName.Contains(searchString)); } switch (sortOrder)

            {

                case "name_desc":

                    students = students.OrderByDescending(s => s.LastName);

                    break;

                case "Date":

                    students = students.OrderBy(s => s.EnrollmentDate);

                    break;

                case "date_desc":

                    students = students.OrderByDescending(s => s.EnrollmentDate);

                    break;

                default:

                    students = students.OrderBy(s => s.LastName);

                    break;

            }



            return View(students.ToList());

        }

  在大多数情况下,我们调用同一个方法时,在EF实体集和内存中集合的扩展方法返回的结果是一样的;但是在一些情况下返回结果会不一样。

  例如当传递一个空的字符串时.NET Framework的Contains方法返回所有行,但是SQL Server Compact 4.0的EF 提供者(provider)的Contains返回0行。因此上面的代码中把Where语句放在if语句中,以保证对所有的SQL Server版本返回相同的数据。同样,.NET Framework的Contains方法默认是区分大小写的,因此,使用ToUpper方法将字符串显示转换为大写以确保以后代码改为仓储时(返回类型由IQueryable类型变成IEnumerable类型)返回结果不会发生变化(当调用Contains方法返回IEnumerable集合时,调用的是.NET Framework实现;返回IQueryable对象时,调用的是数据库提供者的实现)。

  当我们返回IQueryable对象时,不同的数据库提供者对空值的处理也不同。例如,在有些脚本中where条件中的table.Column != 0可能不会返回空值列。

2.2.为Views\Student\Index.cshtml添加搜索框:

<p>

    @Html.ActionLink("Create New", "Create")

</p>

@using (Html.BeginForm())

{

    <p>

        Find by name: @Html.TextBox("SearchString")

        <input type="submit" value="Search" />

    </p>

}

  效果图:

Students_Index_page_with_search_box

3.添加分页

3.1.安装PagedList.MVC:

Install-Package PagedList.Mvc

3.2.修改Controllers\StudentController.cs

using PagedList;
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)

{

   ViewBag.CurrentSort = sortOrder;

   ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";

   ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

  

   if (searchString != null) { page = 1; } else { searchString = currentFilter; }



   ViewBag.CurrentFilter = searchString; var students = from s in db.Students

                  select s;

   if (!String.IsNullOrEmpty(searchString))

   {

      students = students.Where(s => s.LastName.Contains(searchString)

                             || s.FirstMidName.Contains(searchString));

   }

   switch (sortOrder)

   {

      case "name_desc":

         students = students.OrderByDescending(s => s.LastName);

         break;

      case "Date":

         students = students.OrderBy(s => s.EnrollmentDate);

         break;

      case "date_desc":

         students = students.OrderByDescending(s => s.EnrollmentDate);

         break;

      default:  // Name ascending 

         students = students.OrderBy(s => s.LastName);

         break;

   }



   int pageSize = 3; int pageNumber = (page ?? 1); return View(students.ToPagedList(pageNumber, pageSize));

}

  当页面第一次加载或者用户没有点击分页或排序链接时,所有的参数都是空值。

  ViewBag.CurrentSort用于点击分页时保存排序信息。

  ViewBag.CurrentFilter用于保存搜索信息,并且当页面刷新时给搜索框赋值。当搜索条件改变时,page值重置为1。

3.3.修改Views\Student\Index.cshtml

@model PagedList.IPagedList<ContosoUniversity.Models.Student>

@using PagedList.Mvc;

<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />



@{

    ViewBag.Title = "Students";

}



<h2>Students</h2>



<p>

    @Html.ActionLink("Create New", "Create")

</p>

@using (Html.BeginForm("Index", "Student", FormMethod.Get))

{

    <p>

        Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)

        <input type="submit" value="Search" />

    </p>

}

<table class="table">

    <tr>

        <th>

            @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })

        </th>

        <th>

            First Name

        </th>

        <th>

            @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter=ViewBag.CurrentFilter })

        </th>

        <th></th>

    </tr>





@foreach (var item in Model) {

    <tr>

        <td>

            @Html.DisplayFor(modelItem => item.LastName)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.FirstMidName)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.EnrollmentDate)

        </td>

        <td>

            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |

            @Html.ActionLink("Details", "Details", new { id=item.ID }) |

            @Html.ActionLink("Delete", "Delete", new { id=item.ID })

        </td>

    </tr>

}



</table>

<br /> Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount @Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

  BeginForm提交form数据的默认方式是post,post方式是通过HTTP消息体而不是通过URL查询字符串传递参数。我们通过FormMethod.Get把它指定为HTTP GET,这样用户就可以将URL收藏为书签。当动作不会导致更新时W3C HTTP GET使用指南推荐我们使用GET。

  效果图:

Students_index_page_with_paging

4.添加About页面展示Student统计信息

4.1.创建视图模型:

  新建ViewModels文件夹EnrollmentDateGroup.cs

    public class EnrollmentDateGroup

    {

        [DataType(DataType.Date)]

        public DateTime? EnrollmentDate { get; set; }



        public int StudentCount { get; set; }

    }

4.2.修改HomeController.cs

private SchoolContext db = new SchoolContext();

//...

public ActionResult About()

{

    IQueryable<EnrollmentDateGroup> data = from student in db.Students

               group student by student.EnrollmentDate into dateGroup

               select new EnrollmentDateGroup()

               {

                   EnrollmentDate = dateGroup.Key,

                   StudentCount = dateGroup.Count()

               };

    return View(data.ToList());

}

//...

protected override void Dispose(bool disposing)

{

    db.Dispose();

    base.Dispose(disposing);

}

4.3.修改Views\Home\About.cshtml

@model IEnumerable<ContosoUniversity.ViewModels.EnrollmentDateGroup>

           

@{

    ViewBag.Title = "Student Body Statistics";

}



<h2>Student Body Statistics</h2>



<table>

    <tr>

        <th>

            Enrollment Date

        </th>

        <th>

            Students

        </th>

    </tr>



@foreach (var item in Model) {

    <tr>

        <td>

            @Html.DisplayFor(modelItem => item.EnrollmentDate)

        </td>

        <td>

            @item.StudentCount

        </td>

    </tr>

}

</table>

  效果图:

About_page

你可能感兴趣的:(mvc)