上一篇文章实现Student 基本的实体CRUD操作。本文将展示如何Students Index页添加排序、筛选和分页功能。

以下是排序完成时、经过筛选和分页功能截图,您可以在列标题点击排序。

1.为 Students Index页面加入列排序链接

要为Students Index页面加入排序功能,你须要改动Student controller的Index方法,并为Student Index视图加入代码。

向Index方法加入排序功能

打开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());
}

上面的代码接收URL中的查询字符串作为sortOrder參数。该參数是"Name"或"Date"。使用三元运算符推断并加下划线和"desc"来指名这是一个降序排序,默认是按升序排序。

第一次訪问Index页面时是没有查询字符串的,students依照LastName作升序排序显示。这是由switch语句中的default指定的。当用户点击某列的标题链接时,URL的查询字符串中就含有了对应的sortOrder值。

这里使用了两个ViewBag变量以便视图能够将合适的查询字符串提供给列标题链接。

ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ?

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

这里使用了三元运算符,上面第一个指明假如sortOrder參数为null或为空。则ViewBag.NameSortParm被赋值为"name_desc"。否则将其赋值为空。其排序规则为:

Current sort order Last Name Hyperlink Date Hyperlink
Last Name ascending descending ascending
Last Name descending ascending ascending
Date ascending ascending descending
Date descending ascending ascending

该方法使用LINQ to Entities来指明要排序的列,上面的代码在switch语句前新建了一个 IQueryable变量,然后在switch中改动它,最后在switch语句后调用ToList方法。当你创建并改动IQueryable变量时,并没有向数据库发送查询命令,直到调用ToList方法将IQueryable 对象转换为一个集合时才真正的运行查询命令。因此,直到return View语句,才会运行查询语句。

作为还有一种为每个排序编写不同的LINQ语句的替代方法。能够使用动态创建LINQ句。

为Student Index视图加入列标题链接

打开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> @foreach (var item in Model) {

上面的代码使用ViewBag属性使用对应的查询字符串来设置列标题链接的值。

执行项目,点击Last Name和Enrollment Date行标题,验证排序功能





点击Last Name标题。students 将按降序排列

2.向Students Index页面加入搜索框

要在Students Index页面中加入搜索功能,你须要在视图中加入一个文本框和一个提交button并改动Index方法,通过在文本框中输入 first name或者last name 来搜索对应的Students数据。

在Index方法中加入筛选功能

打开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.ToUpper().Contains(searchString.ToUpper())
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
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());
}

上面的代码将searchString參数加入到Index方法。你也能够向LINQ语句中加入where子句来查询那些first name 或者 last name中包括查询条件的student。

查询条件就是你所填写在Index视图的文本框中的字符串,仅仅有当文本框中由查询条件时。where语句才会运行。

注意:在非常多情况下,你能够调用不管该是Entity Framework实体集中的方法还是位于内存集合中的作为扩展的方法,得到的结果一般是一样的,可是有些情况下可能不同。

举例来说。.NET Framework实现了Contains方法,当你向该方法传递一个空字符串作为參数时,它将返回全部行,可是在SQL Server Compact 4.0的  Entity Framework提供程序中不反回不论什么行,因此上面的代码(将where语句放在if语句中)能够确保全部SQL Server版本号都能返回同样的结果。另外,.NET Framework实现的Contains方法默认是大写和小写敏感的,可是Entity Framework SQL Server 提供程序运行的比較是不区分大写和小写的。

因此。此处调用ToUpper方法来明白这里运行不区分大写和小写的比較,这样当接下来使用仓储模式时不须要改动代码就能够得到同样的结果(IEnumerable集合中的Contains方法是由
.NET Framework实现的,IQueryable对象中的Contains方法是由数据库提供程序实现的)。

对于不同的数据库提供程序或者使用IQueryable对象作比較或者使用IEnumerable集合作比較时,Null值得处理也是不同的。比如某些情况下,where条件比方table.Column !=0可能不返回那些包括null值得列。

在Student Index 视图中加入一个搜索框

打开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>
} <table>
<tr>

执行项目。输入要搜索的值,点击Search验证搜索功能是否正常

注意在URL中并不包括搜索字符串,这意味着假设你将此页面增加书签,然后通过书签来打开此页面。你将无法得到筛选后的结果。

在Students Index页面中加入分页功能

要向Students Index页面中加入分页,你须要安装PagedList.Mvc NuGet包。然后你能够在Index 方法中做一些改动并在Index视图中加入分页链接。PagedList.Mvc是ASP.NET MVC中众多分页和排序包中比較好的一个。这里仅仅是使用它来作为演示,并不是作为推荐选择。

安装PagedList.Mvc NuGet包

PagedList包作为PagedList.Mvc包的依赖项会自己主动安装到项目中。PagedList包为IQueryable和IEnumable集合加入了PagedList集合类型和扩展方法。

PagedList扩展方法为从IQueryabl或IEnumable集合产生的PagedList集合数据创建了一个单一的页面。而且PagedList集合提供了多个便于分页的属性和方法。PagedList.Mvc包中含有分页帮助器并可在页面中显示分页button。

依次打开Tools-> Library Package Manager-> Package Manager Console

在打开的Package Manager Console中确保Package source是nuget.org 而且Default project是 ContosoUniversity,最后输入Install-Package PagedList.Mvc命令

在Index方法中加入分页功能

打开Controllers\StudentController.cs,加入PagedList命名空间

using PagedList;

使用以下的代码替换Index方法

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.ToUpper().Contains(searchString.ToUpper())
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
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));
}

上面的代码加入了一个page參数,一个当前排序顺序參数,一个当前搜索条件參数

public ActionResult Index(string sortOrder, string currentFilter, string searchString, int? page)

页面第一次显示或者用户还没有点击分页或排序链接。全部參数值都为null。假设点击分页链接,page变量将包括要显示的页码。

ViewBag属性向视图提供了当前的排序顺序,由于在点击分页链接后必需要保持当前的排序顺序。

ViewBag.CurrentSort = sortOrder;

还有一个属性ViewBag.CurrentFiler向视图提供当前的搜索条件。该值必需要被包括在分页链接中以保证是针对搜索结果进行分页。同一时候在页面又一次显示时,搜索字符串必须显示在搜索框中。假设在分页时改动了搜索字符串。页码必需要被重置为1。由于新的搜索条件可导致不同的搜索结果。当向搜索框输入搜索字符串并点击提交button。这是searchString的值不为null。

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

在该方法的结尾部分,学生IQueryable对象的ToPagedList扩展方法将学生查询转换为一个支持分页的学生集合类型,并将该学生集合传递给视图

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

ToPagedList方法须要一个页码參数。两个问号表示空合并操作符(null-coalescing operator)。空合并操作符为nullable 类型指定默认值,表达式(page ?? 1)表示假设page值不为空就返回该值,否则返回1。

向 Student Index视图加入分页链接

打开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 }))

页面顶部的@model语句指明视图如今获取的是PagedList对象而不是List对象。

using PagedList.Mvc语句能够使MVC帮助器提供分页button。

在代码中使用了 BeginForm 的重载方法并加入了FormMethod.Get 參数。

@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
<p>
Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" />
</p>
}

默认情况下BeginForm 使用POST方式提交表单数据,这意味着參数通过HTTP消息正文传递而不是通过URL查询字符串。当你指定使用HTTP GET时。表单数据通过URL查询字符串来传递。这样能够同意用户将URL保存为书签。

W3C guidelines for the use of HTTP GET推荐你应该在不会更新数据的方法中使用GET方式。

搜索框使用当前的搜索字符串进行初始化,以便在分页的时候不会丢失搜索字符串。

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

列标题链接使用了搜索字符串并将其传递给控制器以便用户能够对搜索结果进行排序。

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

显示当前页码和总页数

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

假设没有要显示的页。就显示"Page 0 of 0"

PagedListPager帮助器显示分页button

@Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )

PagedListPager帮助器提供了多个选项。你能够自己定义URL和样式

执行项目

使用不同的排序方式。并点击分页button跳转至不同的页码,确保分页功能正常,然后输入查询条件,再次验证分页和搜索功能正常。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvam9obnNvbmJsb2c=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

3.创建显示学生统计信息的About页面

要让About页面显示在每个入学日共同拥有多少学生登记,须要将学生分组并进行简单的计算,要做到这些。须要运行下列操作:

  • 须要为要传递给视图的数据创建一个视图模型类
  • 改动Home控制器中的About方法
  • 改动About视图

创建视图模型

创建一个ViewModels目录并加入名为EnrollmentDataGroup.cs的类,使用以下的代码替换

using System;
using System.ComponentModel.DataAnnotations; namespace ContosoUniversity.ViewModels
{
public class EnrollmentDateGroup
{
[DataType(DataType.Date)]
public DateTime? EnrollmentDate { get; set; } public int StudentCount { get; set; }
}
}

改动Home控制器

打开HomeController.cs,在文件顶部加入using语句引入命名空间

using ContosoUniversity.DAL;
using ContosoUniversity.ViewModels;

为数据库上下文加入类变量

public class HomeController : Controller
{
private SchoolContext db = new SchoolContext();

使用以下的代码替换About方法

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());
}

使用LINQ语句对Student实体依照enrollment date分组。计算每一个分组的实体数量,并将结果存储在EnrollmentDateGroup视图模型对象的集合中。

加入Dispose方法

protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}

改动About视图

打开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链接。显示学生统计信息



欢迎转载,请注明文章出处:http://blog.csdn.net/johnsonblog/article/details/38795465

还大家一个健康的网络环境,从你我做起

项目源代码:https://github.com/johnsonz/MvcContosoUniversity

THE END

MVC5 Entity Framework学习参加排序、筛选和排序功能的更多相关文章

  1. MVC5 Entity Framework学习之实现主要的CRUD功能

    在上一篇文章中,我们使用Entity Framework 和SQL Server LocalDB创建了一个MVC应用程序,并使用它来存储和显示数据.在这篇文章中,你将对由 MVC框架自己主动创建的CR ...

  2. MVC5 Entity Framework学习

    MVC5 Entity Framework学习(1):创建Entity Framework数据模型 MVC5 Entity Framework学习(2):实现基本的CRUD功能 MVC5 Entity ...

  3. MVC5 Entity Framework学习之创建复杂的数据模型

    目录(?)[-] 使用属性来自定义数据模型 DataType属性 StringLength属性 Column 属性 完成对Student实体的更改 Required 属性 Display 属性 Ful ...

  4. MVC5 Entity Framework学习之Entity Framework高级功能(转)

    在之前的文章中,你已经学习了如何实现每个层次结构一个表继承.本节中你将学习使用Entity Framework Code First来开发ASP.NET web应用程序时可以利用的高级功能. 在本节中 ...

  5. MVC5 Entity Framework学习之Entity Framework高级功能

    在之前的文章中,你已经学习了怎样实现每一个层次结构一个表继承. 本节中你将学习使用Entity Framework Code First来开发ASP.NET web应用程序时能够利用的高级功能. 在本 ...

  6. MVC5 Entity Framework学习之实现继承

    之前你已经学习了怎样处理并发异常,在本节中你将学习怎样实现继承. 在面向对象的编程中,你能够使用继承来重用代码.接下来你将改动Instructor和Student类,让它们派生自Person基类,该基 ...

  7. Entity Framework 学习

    Entity Framework 学习初级篇1--EF基本概况 Entity Framework 学习初级篇2--ObjectContext.ObjectQuery.ObjectStateEntry. ...

  8. Entity Framework 学习整理(分播客整理)

    MSDN: http://msdn.microsoft.com/en-us/data/aa937723 台湾博客: http://www.dotblogs.com.tw/yc421206/ http: ...

  9. Entity Framework 学习整理

    MSDN: http://msdn.microsoft.com/en-us/data/aa937723 台湾博客: http://www.dotblogs.com.tw/yc421206/ http: ...

随机推荐

  1. git使用ssh密钥和https两种认证方式汇总(转)

    在版本库的SSH方式和HTTPS方式是不同的,具体来说就是url信息的不同,但是,实际的认证机制也是不同的.当建立了本机密钥之后,使用ssh方式实际上是不需要再次认证的,而https则每次需要输入密码 ...

  2. OCP读书笔记(4) - 配置备份设置

    4.Configuring Backup Settings 查看RMAN持久化设置 [oracle@easthome ~]$ rman target / RMAN> show all; SQL& ...

  3. 世界gis相关的资源网站分类整理

    ********************首先介绍个新颖的GIS论坛——GIS520论坛******************** GIS520论坛(共享地信学习资源的专业论坛) www.gis520.c ...

  4. Hbase经常使用命令

    hbase shell命令的使用 再使用hbase 命令之前先检查一下hbase是否执行正常 hadoop@Master:/usr/hbase/bin$ jps 2640 HMaster 27170 ...

  5. BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆

    题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值 考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣. 每一个节点暴力重建一定 ...

  6. VSTO学习笔记(十五)Office 2013 初体验

    原文:VSTO学习笔记(十五)Office 2013 初体验 Office 2013 近期发布了首个面向消费者的预览版本,我也于第一时间进行了更新试用.从此开始VSTO系列全面转向Office 201 ...

  7. 鸟哥Linux私房菜知识点总结6到7章

    近期翻看了一本<鸟哥的Linux私房菜>.这是一本基础的书,万丈高楼平地起.会的不多但能够学.这是我整理的一些知识点.尽管非常基础.希望和大家共同交流. 第6章主机规划与磁盘分区 1.在进 ...

  8. Enum实现单例模式

    package com.wjy.effective; public enum Singleton { INSTANCE; private int numa; private int numb; pub ...

  9. poj2528(线段树)

    题目连接:http://poj.org/problem?id=2528 题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报 分析:离散化+线段树,这题因为每个数字其实表示的是一个单位长度,因 ...

  10. GDAL切割重采样遥感图像

    一个小测试程序开发全过程实录,完全新手入门级的实例,如果你还在为处理大影像而发愁,来试试这个称手的工具吧. Imagec 开发日记 2013-6-25 需求: 影像数据切割,重采样 数据切割的要求是简 ...