[英]Using a PagedList with a ViewModel ASP.Net MVC
我正在嘗試在我的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; }
}
}
我需要將三個表連接到ViewModel並在View中顯示結果。
對於試圖在不修改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.
}
調節器
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);
}
視圖
@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>
首先做,然后或許使用這個!
由於這個問題是關於(視圖)模型的,我將為您提供一個小解決方案,它不僅對分頁有用,而且對於您的應用程序的其余部分,如果您想要將實體分開,僅用於存儲庫,讓應用程序的其余部分處理模型(可以用作視圖模型)。
知識庫
在您的訂單存儲庫(在我的例子中)中,添加一個靜態方法來轉換模型:
public static OrderModel ConvertToModel(Order entity)
{
if (entity == null) return null;
OrderModel model = new OrderModel
{
ContactId = entity.contactId,
OrderId = entity.orderId,
}
return model;
}
在您的存儲庫類下面,添加:
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
});
}
}
然后在你的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().
}
讓我解釋:
靜態ConvertToModel
方法可以被任何其他存儲庫訪問,如上所述,我使用來自某些AddressRepository
ConvertToModel
。
擴展類/方法允許您將實體轉換為模型。 這可以是IQueryable或任何其他列表,集合 。
現在有了神奇之處:如果您在調用SelectOrderModel()
擴展名之前執行了查詢,則擴展內的includeRelations
將為true,因為source
不是數據庫查詢類型(不是linq-to-sql IQueryable
)。 如果是這樣,擴展可以調用整個應用程序中的其他方法/擴展來轉換模型。
現在另一方面:您可以先執行擴展,然后繼續進行LINQ過濾。 過濾最終會在數據庫中發生 ,因為你還沒有做.ToList()
,擴展只是處理你的查詢的一層。 Linq-to-sql最終將知道在數據庫中應用哪些過濾。 inlcudeRelations
將為false,因此它不會調用SQL無法理解的其他c#方法。
一開始看起來很復雜,擴展可能是新的,但它確實很有用。 最后,當你為所有存儲庫設置了它時,只需一個.Include()
額外加載關系。
正如Chris所說,你使用ViewModel的原因並不能阻止你使用PagedList
。 您需要形成一組ViewModel對象,這些對象需要發送到視圖以進行分頁。
以下是有關如何將PagedList
用於viewmodel數據的分步指南。
您的viewmodel( 為簡潔起見,我舉了一個簡單的示例,您可以輕松修改它以滿足您的需求。 )
public class QuestionViewModel
{
public int QuestionId { get; set; }
public string QuestionName { get; set; }
}
你的控制器的索引方法就像
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));
}
和您的索引視圖
@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 }) )
這是我的答案的SO鏈接 ,它有關於如何使用PageList
的分步指南
我修改了代碼如下:
視圖模型
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; }
}
}
調節器
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);
}
視圖
<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>
我希望這會對你有所幫助!!
我想出了如何做到這一點。 我正在構建一個非常類似於您在原始問題中討論的示例/教程的應用程序。
這是代碼片段,對我有用:
int pageSize = 4;
int pageNumber = (page ?? 1);
//Used the following two formulas so that it doesn't round down on the returned integer
decimal totalPages = ((decimal)(viewModel.Teachers.Count() /(decimal) pageSize));
ViewBag.TotalPages = Math.Ceiling(totalPages);
//These next two functions could maybe be reduced to one function....would require some testing and building
viewModel.Teachers = viewModel.Teachers.ToPagedList(pageNumber, pageSize);
ViewBag.OnePageofTeachers = viewModel.Teachers;
ViewBag.PageNumber = pageNumber;
return View(viewModel);
我補充道
using.PagedList;
我的控制器如教程所述。
現在在我看來我在頂部使用語句等,注意我沒有改變我的使用模型語句。
@model CSHM.ViewModels.TeacherIndexData
@using PagedList;
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
然后在底部建立我的分頁列表我使用以下,它似乎工作。 我還沒有內置當前排序的功能,顯示相關的數據,過濾器等,但我不認為這將是那么困難。
Page @ViewBag.PageNumber of @ViewBag.TotalPages
@Html.PagedListPager((IPagedList)ViewBag.OnePageofTeachers, page => Url.Action("Index", new { page }))
希望對你有用。 讓我知道它是否有效!!
您使用視圖模型的事實沒有影響。 使用PagedList
的標准方法是將“一頁項目”存儲為ViewBag
變量。 您需要確定的是您將要分頁的內容。 您不能同時在邏輯上分頁多個集合,因此假設您選擇了Instructors
:
ViewBag.OnePageOfItems = myViewModelInstance.Instructors.ToPagedList(pageNumber, 10);
然后,標准代碼的其余部分一如既往地工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.