Как отсортировать список объектов, используя ViewModel вместо ViewBag? - PullRequest
2 голосов
/ 05 марта 2012

Я использую 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) &nbsp;
        <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
    &nbsp;
    @if (Model.HasPreviousPage)
    {
        @Html.ActionLink("<<", "Index", new { page = 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter  })
        @Html.Raw("&nbsp;");
        @Html.ActionLink("< Prev", "Index", new { page = Model.PageNumber - 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter  })
    }
    else
    {
        @:<<
        @Html.Raw("&nbsp;");
        @:< Prev
    }
    &nbsp;
    @if (Model.HasNextPage)
    {
        @Html.ActionLink("Next >", "Index", new { page = Model.PageNumber + 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter  })
        @Html.Raw("&nbsp;");
        @Html.ActionLink(">>", "Index", new { page = Model.PageCount, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter  })
    }
    else
    {
        @:Next >
        @Html.Raw("&nbsp;")
        @:>>
    }
</div>

Ответы [ 3 ]

1 голос
/ 05 марта 2012

Контроллер должен обрабатывать сортировку, представление просто отображает данные. Вы уже делаете это, так что вам нужно только определить модель представления, которую в первую очередь вы бы поместили в 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
  }
0 голосов
/ 05 марта 2012

Вы можете сделать обертку вокруг вашего класса учеников

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

в вашем View вы бы использовали StudentWrapper

@model List<MVCAppName.Models.StudentWrapper>

Я не знаю, как работает ваш пейджинг, поэтому вам придется это выяснить.

Но я не вижу никаких проблем в использовании ViewBag.

0 голосов
/ 05 марта 2012

Я думаю, что лучше всего было бы создать подкласс 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; }
}
...