Comment puis-je trier une liste d'entités à l'aide de ViewModel au lieu de ViewBag?
Je suis en utilisant ViewBag pour m'aider à trier une liste des étudiants au sein d'une liste de classes. J'ai lu que le ViewBag est quelque chose qui doit être évité à tous les frais de tenter de construire un bon projet MVC.
Lors de l'affichage de la page que le code ci-dessous génère, on est capable de trier une liste d'étudiants dans une variété de façons de (prénom de l'alpha, le nom de l'alpha, la date inscrite, etc), et de n'afficher qu'un nombre limité d'étudiants par page.
Je ne sais pas exactement comment traduire mon code pour utiliser un ViewModel à la place de mon design actuel.
Je suis en utilisant le code suivant:
Modèle (Étudiant):
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; }
}
Modèle (Inscription):
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; }
}
(J'ai aussi un Cours de modèle, mais il n'est pas référencé directement par le contrôleur ci-dessous, je vais donc l'omettre ici - s'il est nécessaire pour afficher les détails, s'il vous plaît laissez-moi savoir.)
Contrôleur:
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));
}
Et de mon point de vue:
@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>
- Au sujet de "j'ai lu que le ViewBag est quelque chose qui doit être évité à tous les frais de tenter de construire un bon projet MVC'. Toute dogmatique, la règle devrait être évitée à tous les frais lors de la construction de n'importe quel logiciel.
- mes coups de gueule sur le viewbag: completedevelopment.blogspot.com/2011/12/...
- Est-ce à dire que si il y avait des contrôles de compilation il n'y aurait pas de stigmatisation avec ViewBag?
Vous devez vous connecter pour publier un commentaire.
Le contrôleur doit gérer le tri, la vue affiche les données. Vous le font déjà, si vous avez besoin seulement de définir le modèle de vue, qui preivosuly vous l'avais mis dans le ViewBag
Puis dans la vue
Je pense que le plus beau serait de sous-classe, les
PagedList.IPagedList<T>
que vous utilisez, et ajouter de tri de l'ordre. Ainsi, à la fin de votre commande, vous auriez ceci:Mais si vous n'êtes pas prêt à faire cela, alors vous pouvez simplement créer une nouvelle classe ViewModel pour tenir le PagedList (votre modèle actuel) ainsi que les données supplémentaires dont vous avez besoin (c'est à dire l'ordre de tri).
Avec le SortedStudents définie comme ceci:
Vous pourriez faire un wrapper autour de vos Élèves de la classe
Dans votre contrôleur, vous devez créer un nouveau StudentWrapper
et définir la liste des étudiants:
et l'ordre de tri
Vous passer de ce modèle à votre Vue
dans votre Vue, vous pouvez utiliser le StudentWrapper
Je ne sais pas comment votre pagination fonctionne, alors vous devez comprendre cela.
Mais je ne vois aucun problème dans l'utilisation de la ViewBag soit.