将PagedList与ViewModel ASP.Net MVC一起使用

lte*_*one 25 c# asp.net-mvc pagedlist asp.net-mvc-viewmodel

我正在尝试在我的ASP.Net应用程序中使用PagedList,我在微软网站上找到了这个例子http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting -filtering-和寻呼与-的实体框架功能于一个-ASP净MVC-应用

在使用ViewModel的复杂情况下如何使用PagedList?我正在尝试添加一个没有成功的PagedList到这里发布的教师示例:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/reading-related-data-with -the-实体框架功能于一个-ASP净MVC-应用

问题是ViewModel由类而不是简单字段组成,因此我无法使用ToPageList()方法转换结果.

这是ViewModel结构:

using System.Collections.Generic;
using ContosoUniversity.Models;

namespace ContosoUniversity.ViewModels
{
    public class InstructorIndexData
    {
        public IEnumerable<Instructor> Instructors { get; set; }
        public IEnumerable<Course> Courses { get; set; }
        public IEnumerable<Enrollment> Enrollments { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要将三个表连接到ViewModel并在View中显示结果.

Cul*_*tes 24

对于试图在不修改ViewModel并且不从数据库中加载所有记录的任何人.

知识库

    public List<Order> GetOrderPage(int page, int itemsPerPage, out int totalCount)
    {
        List<Order> orders = new List<Order>();
        using (DatabaseContext db = new DatabaseContext())
        {
            orders = (from o in db.Orders
                      orderby o.Date descending //use orderby, otherwise Skip will throw an error
                      select o)
                      .Skip(itemsPerPage * page).Take(itemsPerPage)
                      .ToList();
            totalCount = db.Orders.Count();//return the number of pages
        }
        return orders;//the query is now already executed, it is a subset of all the orders.
    }
Run Code Online (Sandbox Code Playgroud)

调节器

    public ActionResult Index(int? page)
    {
        int pagenumber = (page ?? 1) -1; //I know what you're thinking, don't put it on 0 :)
        OrderManagement orderMan = new OrderManagement(HttpContext.ApplicationInstance.Context);
        int totalCount = 0;
        List<Order> orders = orderMan.GetOrderPage(pagenumber, 5, out totalCount);
        List<OrderViewModel> orderViews = new List<OrderViewModel>();
        foreach(Order order in orders)//convert your models to some view models.
        {
            orderViews.Add(orderMan.GenerateOrderViewModel(order));
        }
        //create staticPageList, defining your viewModel, current page, page size and total number of pages.
        IPagedList<OrderViewModel> pageOrders = new StaticPagedList<OrderViewModel>(orderViews, pagenumber + 1, 5, totalCount);
        return View(pageOrders);
    }
Run Code Online (Sandbox Code Playgroud)

视图

@using PagedList.Mvc;
@using PagedList; 

@model IPagedList<Babywatcher.Core.Models.OrderViewModel>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<div class="container-fluid">
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    @if (Model.Count > 0)
    {


        <table class="table">
          <tr>
            <th>
                @Html.DisplayNameFor(model => model.First().orderId)
            </th>
            <!--rest of your stuff-->
        </table>

    }
    else
    {
        <p>No Orders yet.</p>
    }
    @Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
</div>
Run Code Online (Sandbox Code Playgroud)

奖金

首先做,然后或许使用这个!

由于这个问题是关于(视图)模型的,我将为您提供一个小解决方案,它不仅对分页有用,而且对于您的应用程序的其余部分,如果您想要将实体分开,仅用于存储库,让应用程序的其余部分处理模型(可以用作视图模型).

知识库

在您的订单存储库(在我的例子中)中,添加一个静态方法来转换模型:

public static OrderModel ConvertToModel(Order entity)
{
    if (entity == null) return null;
    OrderModel model = new OrderModel
    {
        ContactId = entity.contactId,
        OrderId = entity.orderId,
    }
    return model;
}
Run Code Online (Sandbox Code Playgroud)

在您的存储库类下面,添加:

public static partial class Ex
{
    public static IEnumerable<OrderModel> SelectOrderModel(this IEnumerable<Order> source)
    {
        bool includeRelations = source.GetType() != typeof(DbQuery<Order>);
        return source.Select(x => new OrderModel
        {
            OrderId = x.orderId,
            //example use ConvertToModel of some other repository
            BillingAddress = includeRelations ? AddressRepository.ConvertToModel(x.BillingAddress) : null,
            //example use another extension of some other repository
            Shipments = includeRelations && x.Shipments != null ? x.Shipments.SelectShipmentModel() : null
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的GetOrderPage方法中:

    public IEnumerable<OrderModel> GetOrderPage(int page, int itemsPerPage, string searchString, string sortOrder, int? partnerId,
        out int totalCount)
    {
        IQueryable<Order> query = DbContext.Orders; //get queryable from db
        .....//do your filtering, sorting, paging (do not use .ToList() yet)

        return queryOrders.SelectOrderModel().AsEnumerable();
        //or, if you want to include relations
        return queryOrders.Include(x => x.BillingAddress).ToList().SelectOrderModel();
        //notice difference, first ToList(), then SelectOrderModel().
    }
Run Code Online (Sandbox Code Playgroud)

让我解释:

静态ConvertToModel方法可以被任何其他存储库访问,如上所述,我使用的ConvertToModel是一些AddressRepository.

扩展类/方法允许您将实体转换为模型.这可以是IQueryable或任何其他列表,集合.

现在有了神奇之处:如果你在调用SelectOrderModel()扩展之前执行了查询,includeRelations那么扩展内部将是真的,因为source它不是数据库查询类型(不是linq-to-sql IQueryable).如果是这样,扩展可以调用整个应用程序中的其他方法/扩展来转换模型.

现在另一方面:您可以先执行扩展,然后继续进行LINQ过滤.过滤最终会在数据库中进行,因为您还没有进行过.ToList(),扩展只是处理查询的一层.Linq-to-sql最终会知道在数据库中应用哪些过滤.这inlcudeRelations将是false,因此它不会调用SQL无法理解的其他c#方法.

一开始看起来很复杂,扩展可能是新的,但它确实很有用.最后,当你为所有存储库设置了它时,只需要一个.Include()额外的加载关系.

  • 绝对是我迄今为止发现的最佳解决方案.所有其他的,包括Microsoft教程,都不像在真实的商业环境中那样使用分层体系结构,而是从控制器直接进入存储库并将PagedList作为模型中唯一的对象传回. (2认同)

Den*_*s R 16

正如克里斯所说,你使用ViewModel的原因并没有阻止你使用PagedList.您需要形成一组ViewModel对象,这些对象需要发送到视图以进行分页.

以下是有关如何使用PagedListviewmodel数据的分步指南.

您的viewmodel(为简洁起见,我举了一个简单的示例,您可以轻松修改它以满足您的需求.)

public class QuestionViewModel
{
        public int QuestionId { get; set; }
        public string QuestionName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

你的控制器的索引方法就像

public ActionResult Index(int? page)
{
     var questions = new[] {
           new QuestionViewModel { QuestionId = 1, QuestionName = "Question 1" },
           new QuestionViewModel { QuestionId = 1, QuestionName = "Question 2" },
           new QuestionViewModel { QuestionId = 1, QuestionName = "Question 3" },
           new QuestionViewModel { QuestionId = 1, QuestionName = "Question 4" }
     };

     int pageSize = 3;
     int pageNumber = (page ?? 1);
     return View(questions.ToPagedList(pageNumber, pageSize));
}
Run Code Online (Sandbox Code Playgroud)

和您的索引视图

@model PagedList.IPagedList<ViewModel.QuestionViewModel>
@using PagedList.Mvc; 
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />


<table>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.QuestionId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.QuestionName)
        </td>
    </tr>
}

</table>

<br />

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount
@Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )
Run Code Online (Sandbox Code Playgroud)

这是我的答案的SO链接,它有关于如何使用的分步指南PageList


lte*_*one 13

我修改了代码如下:

视图模型

using System.Collections.Generic;
using ContosoUniversity.Models;

namespace ContosoUniversity.ViewModels
{
    public class InstructorIndexData
    {
     public PagedList.IPagedList<Instructor> Instructors { get; set; }
     public PagedList.IPagedList<Course> Courses { get; set; }
     public PagedList.IPagedList<Enrollment> Enrollments { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

调节器

public ActionResult Index(int? id, int? courseID,int? InstructorPage,int? CoursePage,int? EnrollmentPage)
{
 int instructPageNumber = (InstructorPage?? 1);
 int CoursePageNumber = (CoursePage?? 1);
 int EnrollmentPageNumber = (EnrollmentPage?? 1);
 var viewModel = new InstructorIndexData();
 viewModel.Instructors = db.Instructors
    .Include(i => i.OfficeAssignment)
    .Include(i => i.Courses.Select(c => c.Department))
    .OrderBy(i => i.LastName).ToPagedList(instructPageNumber,5);

 if (id != null)
 {
    ViewBag.InstructorID = id.Value;
    viewModel.Courses = viewModel.Instructors.Where(
        i => i.ID == id.Value).Single().Courses.ToPagedList(CoursePageNumber,5);
 }

 if (courseID != null)
 {
    ViewBag.CourseID = courseID.Value;
    viewModel.Enrollments = viewModel.Courses.Where(
        x => x.CourseID == courseID).Single().Enrollments.ToPagedList(EnrollmentPageNumber,5);
 }

 return View(viewModel);
}
Run Code Online (Sandbox Code Playgroud)

视图

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

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

</div>
Run Code Online (Sandbox Code Playgroud)

我希望这会对你有所帮助!!