本篇原文地址:Sorting, Filtering, and Pagingcss
說明:學習筆記參考原文中的流程,爲了增長實際操做性,並可以深刻理解,部分地方根據實際狀況作了一些調整;而且根據本身的理解作了一些擴展。git
本人的學習環境: VS2017 + EF 6.1.3 + .NET 4.6.1github
上一篇完成基本的CRUD操做;本篇學習如何進行排序顯示、過濾查詢及分頁顯示;數據庫
Step1 排序顯示,主要是對Student列表頁面進行點擊表列頭進行該列排序;點擊一次從正序變爲反序,再點擊一次從反序變爲正序;bootstrap
Student 控制器 Index Action 代碼改成: (目前先只考慮了LastName和EnrollmentDate的排序 ) 服務器
public ActionResult Index(string sortOrder) {
//若是sortOrder爲空,則把name_desc值傳到view保存,下一次點擊列頭進行請求的時候,就會帶回這個值,表示下一次用 Desc 倒序方式;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
//同理若是sortOrder爲Date,則把date_desc值傳到view保存,下一次點擊列頭進行請求時,帶回這個值,表示下一次用 Date 倒序方式; 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()); }
對於View 的列頭部分,修改成如下代碼:mvc
<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>
排序操做主要是巧妙的利用ViewBag裏設置一個Sort值來進行來回請求的時候進行開關切換,傳進來是正序的ViewBag參數,則返回View的時候,把ViewBag參數改成倒序,這樣下次請求的時候,參數就是倒序的ViewBag參數,再在返回View的時候,把參數改成正序,這樣就能夠實現點一次變換正反序的想法。app
而後再利用EF先查詢出全部學生記錄,再利用OrderBy 或者 OrderByDescending來進行數據排序,最後把排序結果返回給View去顯示;ide
Step2 檢索過濾,這個相對比較簡單,主要是利用EF查詢的時候經過where加Lamda表達式來篩選出符合條件的數據。post
先在View中增長一個過濾檢索條件的輸入框:(就增長在Create的<p>和主Table之間)
@using (Html.BeginForm())
{
<p>
Find by name: @Html.TextBox("SearchString")
<input type="submit" value="Search" />
</p>
}
Index Action中增長過濾操做:
public ActionResult 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());
}
//後續增長一些思考
Step3 分頁顯示
原文采用PagedList.Mvc 而PagedList的github頁面顯示 PagedList已經再也不維護升級,建議使用X.PagedList替代;
注:要用X.PagedList.Mvc的話,.net 必須4.5.2以上版本才能夠;
下面用X.PagedList.Mvc來完成後續分頁測試;
先經過NuGet安裝: Install-Package X.PagedList.Mvc
(如今NuGet常常沒法直接安裝。。。頭疼)
Student 控制器先增長申明: using X.PagedList;
Index Action 代碼修改成:
public ActionResult Index(string sortOrder, string searchString, int? page) { //若是sortOrder爲空,則把name_desc值傳到view保存,下一次點擊列頭進行請求的時候,就會帶回這個值,表示下一次用 Desc 倒序方式; ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : ""; //同理若是sortOrder爲Date,則把date_desc值傳到view保存,下一次點擊列頭進行請求時,帶回這個值,表示下一次用 Date 倒序方式; 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; } var pageNumber = page ?? 1;
//簡單固定數量分頁,每頁3條記錄,若是要動態數量,須要修改 var onePageOfStudents = students.ToPagedList(pageNumber, 3); return View(onePageOfStudents); }
View變動爲:
@model IEnumerable<EFTest.Models.Student> @{ ViewBag.Title = "Index"; } @using X.PagedList.Mvc; @using X.PagedList; <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> @using (Html.BeginForm()) { <p> Find by name: @Html.TextBox("SearchString") <input type="submit" value="Search" /> </p> } <table class="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> @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> @Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page }))
實現效果:
X.PagedList.Mvc 比原來的PagedList.Mvc簡單很多;
(CSS樣式是Twitter Bootstrap 樣式的,也能夠根據本身要求自定義,在Package裏也有PagedList.css能夠用
)
之前寫的所謂這種方式是假分頁的話是錯的,收回。
經過下一章的命令攔截調試,能夠看到執行的SQL語句,理論上應該是服務器端真分頁,SQL語句只執行取總行數以及當前請求頁的數據:
最後作一個Student的統計頁面:
主要3步:
一、新建一個ViewModel用於顯示統計數據;
二、修改Home\About Action;
三、修改About 對應的視圖
using System; using System.ComponentModel.DataAnnotations; namespace EFTest.ViewModels { public class EnrollmentDateGroup { [DataType(DataType.Date)] public DateTime? EnrollmentDate { get; set; } public int StudentCount { get; set; } } }
Home 控制器加入如下申明:
using EFTest.DAL; using EFTest.ViewModels;
Home 控制器加入上下文私有屬性:
private SchoolContext db = new SchoolContext();
Home 控制器加入About Action :
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); }
爲About Action新建一個空視圖,而後用如下代碼替換:
@model IEnumerable<EFTest.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>
最後運行起來看下效果,點擊Home 頁 About 按鈕: