我正在使用ViewBag来帮助我对在课程列表中找到的学生列表进行排序。我已经读过ViewBag应该不惜一切代价避免尝试构建一个合适的MVC项目。
当查看以下代码生成的页面时,可以通过各种方式对学生列表进行排序(按名字分类,按字母分类的姓氏,注册日期等),并查看仅限制每页学生人数。
我不知道如何翻译我的代码以使用ViewModel代替我当前的设计。
我使用以下代码:
模特(学生):
public class Student
{
public int StudentID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public string Email { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
模型(注册):
public class Enrollment
{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public string Grade { get; set; } // pass, fail, incomplete
public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
(我也有一个课程模型,但下面的控制器没有直接引用它,所以我在这里省略它 - 如果有必要显示它的详细信息,请告诉我。)
控制器:
public class StudentController : Controller
{
private SchoolContext db = new SchoolContext();
//
// GET: /Student/
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";
ViewBag.FNameSortParm = sortOrder == "FName" ? "FName desc" : "FName";
ViewBag.EmailSortParm = sortOrder == "Email" ? "Email desc" : "Email";
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;
case "FName":
students = students.OrderBy(s => s.FirstMidName);
break;
case "FName desc":
students = students.OrderByDescending(s => s.FirstMidName);
break;
case "Email":
students = students.OrderBy(s => s.Email);
break;
case "Email desc":
students = students.OrderByDescending(s => s.Email);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
int pageSize = 4;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));
}
我的观点:
@model PagedList.IPagedList<MVCAppName.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>
@Html.ActionLink("First Name", "Index", new { sortOrder = ViewBag.FNameSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
@Html.ActionLink("Email", "Index", new { sortOrder = ViewBag.EmailSortParm, currentFilter = ViewBag.CurrentFilter })
</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.Email)
</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>
答案 0 :(得分:1)
控制器应该处理排序,视图只显示数据。你已经这样做了,所以你只需要定义视图模型,这个模型可以放在ViewBag中。
public class ShowStudentsModel
{
public string CurrentSort {get;set;}
public string NameSortParm {get;set;}
//and so on... you create a property for each property set in the ViewBag
public IEnumerable<Student> Students {get;set;}
}
然后在视图中
@model ShowStudentsModel
@foreach(var item in Model.Students)
{
//html code
}
答案 1 :(得分:0)
我认为最好的方法是继承你正在使用的PagedList.IPagedList<T>
并在那里添加排序顺序。所以在你的控制器结束时你会有这个:
return View(students.ToPagedList(pageNumber, pageSize, sortOrder));
但如果您不愿意这样做,那么您可以简单地创建一个新的ViewModel类来保存PagedList(您当前的模型)以及您需要的补充数据(即您的排序顺序)。
return View(new SortedStudents
{
Students = students.ToPagedList(pageNumber, pageSize);
SortOrder = sortOrder
});
SortedStudents定义如下:
public class SortedStudents
{
public PagedList.IPagedList<MVCAppName.Models.Student> Students { get; set; }
public string SortOrder { get; set; }
}
答案 2 :(得分:0)
你可以围绕学生班制作一个包装
public class StudentWrapper
{
List<Students> studentList { get; set; }
String currentSort { get; set; }
public StudentWrapper() {
studentlist = new List<Students>();
}
在您的控制器中,您将创建一个新的StudentWrapper
StudentWrapper sw = new StudentWrapper();
并设置学生列表:
sw.studentList = db.Students.ToList();
和sortOrder
sw.currentSort = SortOder;
您将此模型传递给视图
return View(sw);
在您的视图中,您将使用StudentWrapper
@model List<MVCAppName.Models.StudentWrapper>
我不知道你的传呼是如何工作的,所以你必须弄清楚这一点。
但是我也没有看到使用ViewBag的任何问题。