3-1  在 Students 的 Index 页面增加列标题链接

为 Index 页面增加排序的功能,我们需要修改 Student 控制器的 Index 方法,还需要为 Student 视图增加代码。

3-1-1  为 Index 方法增加排序功能

打开 Controllers\StudentController.cs,将 Index 方法替换为如下的代码。

public ViewResult 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 的参数,这个参数由 ASP.NET MVC 作为参数传递给 Action 方法。这个参数可以是  “Name” 或者 “Date”, 可能还有一个空格隔开的 desc 来指定降序。

当第一次请求 Index 的时候,没有参数,学生使用 LastName 的升序顺序显示。这是通过 switch 的 default 代码段指定的,当用户点击一个列的标题链接的时候,合适的 sortOrder 值需要通过查询字符串传递进来。

两个 ViewBag 变量用来为视图提供合适的查询字符串链接值。

ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date";

这里使用了条件语句,第一个用来指定当 sortOrder 参数为 null 或者空串的时候, ViewBag.NameSortParm 应用被设置为 Name desc,其他情况下,应该被设置为空串。

这里有四种可能,依赖于当前的排序情况:

  • 如果当前的排序规则为 LastName 升序,那么,LastName 链接应该设置为降序,Enrollment Date 链接必须被设置为按日期升序。
  • 如果当前的排序规则为 LastName 降序,那么,LastName 链接应该设置为升序,排序串应该为空串,日期为升序。
  • 如果当前排序的规则为 Date 升序,那么,链接应该为 LastName 升序和日期升序。
  • 如果当前的排序规则为 Date 降序,那么,链接应该为 LastName 升序和日期降序。

方法中使用 LINQ to Entities 来指定排序,在 switch 之前,代码首先创建一个 IQueryable 变量,在 switch 语句中修改这个查询表达式,最后调用 ToList 方法。在创建和修改查询表达式 IQueryable 的时候,并没有将查询发送到数据库中执行,查询直到将 IQueryable 对象驼工调用类似 ToList 方法转换到集合对象的时候才会执行,因此,代码中查询直到最后的 return View 才会被执行。

3-2-2  为 Index 视图增加列标题链接

在 Views\Student\Index.cshtml,使用如下的代码替换标题行中的 <tr> 和 <th> 元素。

<tr>
<th></th>
<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>
</tr>

这段代码使用 ViewBag 属性来设置超级链接中包含适当的查询字符串。

运行页面,点击列标题,来验证排序是否正常。

aaarticlea/png;base64,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" alt="" />

3-2  为 Index 页面增加搜索框

为 Index 页面增加过滤功能,需要增加一个文本框和一个提交按钮,然后,对 Index 方法进行一些修改,文本框允许你输入一个搜索字符串,用来在 FirstName 和 LastName 中进行搜索。

3-2-1  为 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());
}

现在,为 Index 方法增加了一个参数 searchString ,LINQ 语句中也增加了一个 where 子句,用来选择在 FirstName 或者 LastName 中包含过滤字符串的学生。搜索串来自文本框的输入,后面需要你在视图中加入它。增加的 where 条件子句仅仅在提供了搜索串的情况下才会被处理。

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

注意:在传递一个空串的时候,.NET 实现的 Contains 方法将会返回所有的数据行,但是 EF Provider for SQL Server Compact 4.0 对于空串不返回任何行。因此,代码中增加了一个 if 判断语句,以确保对于所有的 SQL Server 都有一致的处理结果。另外,.NET 实现的 Contains 默认进行区分大小写的字符串比较,因此,通过调用 ToUpper 方法显式转换字符串为大写,

以确保在转换到使用资源库模式的时候不需要修改代码。那个时候将会返回一个 IEnumerable 集合而不是 IQueryable 对象 ( 在调用 IEnumerable 集合上的 Contains 方法的时候,使用 .NET 实现的方法,在调用 IQueryable 对象上的 Contains 方法的时候,使用数据库 Provider 提供的实现 )。

3-2-2  在 Student 视图上加入搜索框

在视图 Views\Student\Index.cshtml 上,table 开始标记之前,增加一个标题,一个文本框,以及一个 Search 按钮。

@using (Html.BeginForm())
{
<p>
Find by name: @Html.TextBox("SearchString")
<input type="submit" value="Search" /></p>
}

运行程序,输入一个搜索串,然后点击 Search 按钮来查看过滤的效果。

3-3  在 Student 的 Index 视图上增加分页

为了支持分页,你需要通过 NuGet 包管理器安装 PagedList ,然后,需要在 Index 方法中增加一些代码,在视图中增加分页的链接,下面的截图展示了分页的链接。

3-3-1  安装 PagedList 包

NuGet 中的 PagedList 包将会增加一种类型:PagedList,当将查询结果传入到 PagedList 中后,它提供的一系列属性和方法使得排序更加简单。

在 Visual Studio 中,确信选中了当前的项目,而不是解决方案。在 Tools 菜单中,选择 Library Package Manager,然后选择 Add Library Package Reference。

在 Add Library Package Reference 对话框中,点击左边的 Online 窗格,然后在搜索框中输入 pagedlist ,在看到 PagedList 包之后,点击 Install。

3-3-2  为 Index 方法增加分页功能

打开 Controllers\StudentController.cs,在代码的前面为 PagedList 命名空间增加 using 语句.

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 (Request.HttpMethod == "GET")
{
searchString = currentFilter;
}
else
{
page = 1;
}
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:
students = students.OrderBy(s => s.LastName);
break;
} int pageSize = 3;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));
}

方法又增加了一个 page 参数,方法的签名如下所示。

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

当第一次显式这个页面的时候,或者用户没有点击分页链接的时候,page 参数将会是 null。如果分页链接被点击了,page 参数将会包含需要显示的页码。

ViewBag 中的 CurrentSort 属性用来提供当前的排序顺序,它必须被包含到当前的分页链接中,以便在分页处理过程中保持当前的排序规则。

ViewBag.CurrentSort = sortOrder;

其它的 ViewBag 属性为视图提供当前的过滤串,因为这个过滤串在页面被重新显示的时候,必须重新回到文本框中,另外,这个串也必须包含在分页链接中,以便在分页过程中,保持过滤效果。最后,如果在分页的过程中修改了过滤串,那么页码将会回到第一页,因为新的过滤规则返回了不同的数据,很可能原来的页码在这时候已经不再存在了。

if (Request.HttpMethod == "GET")
{
searchString = currentFilter;
}
else
{
page = 1;
}
ViewBag.CurrentFilter = searchString;

在方法的最后,查询学生的表达式被转换为 PagedList ,而不再是通常的 List,这样传递到视图中的就是支持分页的集合,代码如下:

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

ToPagedList 方法需要一个页码值,两个问号用来为可空的页码提供一个默认值,表达式 ( page ?? 1 ) 意味着如果 page 有值得话返回这个值,如果是 null 的话,返回 1。

3-3-3  为视图增加分页链接

在 Views\Student\Index.cshtml中,使用下面的代码替换原有代码。

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

@{
ViewBag.Title = "Students";
} <h2>Students</h2> <p>
@Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm())
{
<p>
Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" /></p>
}
<table>
<tr>
<th></th>
<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>
</tr> @foreach (var item in Model) {
<tr>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.StudentID }) |
@Html.ActionLink("Details", "Details", new { id=item.StudentID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.StudentID })
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
</tr>
} </table> <div>
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of @Model.PageCount @if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "Index", new { page = 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink("< Prev", "Index", new { page = Model.PageNumber - 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
}
else
{
@:<<
@Html.Raw(" ");
@:< Prev
} @if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "Index", new { page = Model.PageNumber + 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink(">>", "Index", new { page = Model.PageCount, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
}
else
{
@:Next >
@Html.Raw(" ")
@:>>
}
</div>

视图最前面的 @model 语句指定现在传递到视图的不再是 List 而是 PagedList 。

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

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

列的标题链接使用查询串来传递当前的搜索串,以便传递给控制器当前的搜索和排序。

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

在当前页面的最后,通过一行来显示分页的导航 UI。

Page [current page number] of [total number of pages] << < Prev Next > >>

<< 符号连接到第一页, < Prev 链接到上一页,等等。如果用户当前就在第一页,那么,链接到第一页的链接就会被禁用,类似地,如果用户当前在最后一页,导航到最后一页就会被禁用,每一个分页链接传递页码以及当前的排序串和搜索串到控制器,这使得可以在分页的同时维护排序和过滤规则。

如果没有页可以显示,将会显示 “Page 0 of 0 “,在这种情况下,页面数字就会大于页数,因为 Model.PageNumber 是 1,但是 Model.PageCount 为 0。

运行页面。

在不同的排序规则下,点击分页链接,确认分页在正常工作。然后输入一个过滤串,再次点击分页的链接,确认在排序和过滤的同时,分页可以正常工作。

3-4  创建 About 页面显示学生的统计情况

在 Contoso 大学网站的 About 页面,我们希望能够显示每个注册日有多少学生注册。这需要进行分组,然后在每个组上进行简单地计算,需要完成下列工作:

  • 创建用于传递数据到视图的 ViewModel
  • 修改 Home 控制器中的 About 方法
  • 修改 About 视图

3-4-1  创建 ViewModel

创建 ViewModels 文件夹,在文件夹中,创建 EnrollmentDateGroup.cs 类文件,将代码替换为如下代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace ContosoUniversity.ViewModels
{
public class EnrollmentDateGroup
{
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? EnrollmentDate { get; set; } public int StudentCount { get; set; }
}
}

3-4-2  修改 Home 控制器

增加如下的 using 语句。

using ContosoUniversity.DAL;
using ContosoUniversity.Models;
using ContosoUniversity.ViewModels;

增加一个数据库上下文变量。

private SchoolContext db = new SchoolContext();

使用如下的代码替换 About 方法。

public ActionResult About()
{
var 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);
}

LINQ 语句通过注册日期对学生进行分组,计算每一组中的实体数量,最后将查询结果保存为 EnrollmentDateGroup 对象。

3-4-3  增加 Dispose 方法

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

3-4-4  修改 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>
@String.Format("{0:d}", item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

运行页面,每个注册日注册学生的数量显示在表格中。

现在,你已经看到了如何创建数据模型,以及实现基本的增、删、改、查处理,排序、过滤、分页和分组功能。下一次,我们将会扩展数据模型开始更加高级的内容。

在 Students 的 Index 页面增加列标题链接(排序),分页,过滤和分组功能的更多相关文章

  1. zk listbox 点击列标题实现排序功能

    前台(test.zul): <?page title="测试" contentType="text/html;charset=UTF-8"?> &l ...

  2. Cube中维度排序-通过在数据仓库增加列来实现排序

    数据仓库增加排序列: 维度设置: 正确结果:

  3. C# listview 单击列头实现排序 <二>

    单击列头实现排序,首先在羡慕中添加下面的帮助实现的类:具体的代码: using System; using System.Collections; using System.Windows.Forms ...

  4. [转]C# ListView 单击标题实现排序(在转载的基础上有所完善)

    using System; using System.Collections; using System.Windows.Forms; //在转载的基础上有所完善 namespace TDRFacto ...

  5. SharePoint 列表中增加列编辑功能菜单

    需求描述 在企业的部署中,经常将SharePoint和TFS集成在一起,两个系统之间相互读取数据,展现开发进度.在TFS 2018之前版本中,由于TFS的门户定制功能有限,用户比较喜欢使用ShareP ...

  6. pandas删除行删除列,增加行增加列

    创建df: >>> df = pd.DataFrame(np.arange(16).reshape(4, 4), columns=list('ABCD'), index=list(' ...

  7. mxonline实战13,授课讲师列表页,详情页,index页面全局导航

    对应github地址:第13天   把teacher-list.html和teacher-detail.html拷贝过来   一. 授课讲师列表页   1. 修改html文件 把org-list.ht ...

  8. element-ui自定义table表头,修改列标题样式

    elementUI table表格一般的样式是这样的: 但是要改变表头是比较麻烦的一个事情,但是往往有些项目是需要的比如改成如下样式: 一般直接改起来挺麻烦,好在官网提供了一个方法:render-he ...

  9. 【LeetCode-面试算法经典-Java实现】【168-Excel Sheet Column Title(Excell列标题)】

    [168-Excel Sheet Column Title(Excell列标题)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a positive in ...

随机推荐

  1. IO-Polling的代码分析

    在前一篇文章<IO-Polling实现分析与性能评測>中提到了IO-Polling与中断的原理差别,并通过两种模式下NVMe SSD的性能測试对两者进行了对照. 这篇文章将深入到IO-Po ...

  2. Android无线测试之—Genymotion模拟器环境搭建

    genymotion是一款号称速度最快性能最好的android模拟器,它基于Oracle VM VirtualBox.支持GPS.重力感应.光.温度等诸多传感器:支持OpenGL 3D加速:电池电量模 ...

  3. Coursera课程《Machine Learning》学习笔记(week2)

    1 特征 1-1 什么是特征? 我的理解就是,用于描述某个样本点,以哪几个指标来评定,这些个指标就是特征.比方说对于一只鸟,我们评定的指标就可以是:(a)鸟的翅膀大还是小?(b)鸟喙长还是短?(c)鸟 ...

  4. EasyNVR智能云终端接入AI视频智能分析功能,用户可自定义接入自己的分析算法

    视频分析的需求 人工智能的发展和在行业中的作用就不用多说了,已经到了势在必行的一个程度了,尤其是对于流媒体音视频行业来说,这基本上是人工智能重中之重的领域,视频人工智能,也就是视频视觉分析的应用方式大 ...

  5. inner join和out join的区别

    inner join(又叫join) out join包括left join,right join和full join(也就是left+right)

  6. Sql注入基础_access注入

    1.access注入攻击片段-联合查询 2.access注入攻击片段-逐字猜解法 3.Access偏移注入(表名和列名猜解成功率不是百分百,猜解不到) access注入攻击片段-联合查询法 判断注入 ...

  7. 学习 SSH

    ssh_config 与 sshd_config ssh_config: configuration file for the ssh client on the host machine you a ...

  8. 基于apache —HttpClient的小爬虫获取网页内容

    今天(17-03-31)忙了一下午研究webmagic,发现自己还太年轻,对于这样难度的框架(类库) 还是难以接受,还是从基础开始吧,因为相对基础的东西教程相多一些,于是乎我找了apache其下的 H ...

  9. 一个jsp页面引入另一个jsp页面的三种方式 及静态引入和动态引入的区别

    转载下, 转载自:http://blog.csdn.net/fn_2015/article/details/70311495 1.第一种:jstl  import <c:import url=& ...

  10. MySQL中myisam和innodb的主键索引有什么区别?

    MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址.下图是MyISAM索引的原理图: 这里设表一共有三列,假设我们以Col1为主键,则上图是一个MyISAM表的主索 ...