paginacion pagelist net mvc framework example data asp c# asp.net-mvc asp.net-mvc-viewmodel pagedlist

c# - pagelist - Usando un PagedList con un ViewModel ASP.Net MVC



pagination asp net c# (5)

Como Chris sugirió que la razón por la que estás usando ViewModel no te impide usar PagedList . Debe formar una colección de sus objetos de ViewModel que deben enviarse a la vista para paginar.

Aquí hay una guía paso a paso sobre cómo puede usar PagedList para los datos de su modelo de visualización.

Su modelo de vista ( Tomé un ejemplo simple para abreviar y puede modificarlo fácilmente para que se ajuste a sus necesidades ) .

public class QuestionViewModel { public int QuestionId { get; set; } public string QuestionName { get; set; } }

y el método de índice de su controlador será algo así como

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

Y tu vista de índice

@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 }) )

Aquí está el enlace SO con mi respuesta que tiene la guía paso a paso sobre cómo puede usar PageList

Estoy intentando usar una PagedList en mi aplicación ASP.Net y encontré este ejemplo en el sitio web de Microsoft http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application

¿Cómo es posible usar una PagedList en una situación compleja que usa un ViewModel? Estoy intentando agregar una PagedList sin éxito al ejemplo de Instructor publicado aquí: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application

El problema es que ViewModel está compuesto por clases y no campos simples, por lo que no puedo convertir el resultado con el método ToPageList ().

Esta es la estructura de 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; } } }

Necesito unir las tres tablas en el ViewModel y mostrar el resultado en una Vista.


Descubrí cómo hacer esto. Estaba creando una aplicación muy similar al ejemplo / tutorial que mencionaste en tu pregunta original.

Aquí hay un fragmento del código que funcionó para mí:

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

yo añadí

using.PagedList;

a mi controlador como lo indica el tutorial.

En mi opinión, mis declaraciones de uso, etc. en la parte superior, NOTA, no cambié mi declaración de uso.

@model CSHM.ViewModels.TeacherIndexData @using PagedList; @using PagedList.Mvc; <link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

y luego, en la parte inferior, para construir mi lista de páginas, utilicé lo siguiente y parece funcionar. Todavía no he incorporado la funcionalidad para la clasificación actual, mostrando datos relacionados, filtros, etc., pero no creo que sea tan difícil.

Page @ViewBag.PageNumber of @ViewBag.TotalPages @Html.PagedListPager((IPagedList)ViewBag.OnePageofTeachers, page => Url.Action("Index", new { page }))

Espero que eso te funcione. ¡¡Déjame saber si funciona!!


El hecho de que estés usando un modelo de vista no tiene ningún rumbo. La forma estándar de usar PagedList es almacenar "una página de elementos" como una variable ViewBag . Todo lo que tiene que determinar es qué colección constituye lo que se paginará. Lógicamente, no puede paginar varias colecciones al mismo tiempo, por lo que suponiendo que elija Instructors :

ViewBag.OnePageOfItems = myViewModelInstance.Instructors.ToPagedList(pageNumber, 10);

Luego, el resto del código estándar funciona como siempre lo ha hecho.


He modificado el código de la siguiente manera:

ViewModel

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

Controlador

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

Ver

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

Espero que esto te ayude !!


Para cualquier persona que intente hacerlo sin modificar sus ViewModels Y no cargue todos sus registros de la base de datos.

Repositorio

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. }

Controlador

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

Ver

@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>

Prima

¡Haga arriba primero, luego tal vez use esto!

Ya que esta pregunta es sobre modelos (de vista), le daré una pequeña solución para usted que no solo será útil para la paginación, sino también para el resto de su aplicación si desea mantener sus entidades separadas, solo se usa en el repositorio, y hacer que el resto de la aplicación se ocupe de los modelos (que se pueden usar como modelos de vista).

Repositorio

En su repositorio de pedidos (en mi caso), agregue un método estático para convertir un modelo:

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

Debajo de tu clase de repositorio, agrega esto:

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

Y luego en su método 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(). }

Dejame explicar:

Se puede acceder al método ConvertToModel estático desde cualquier otro repositorio, como se usa anteriormente, uso ConvertToModel desde algún AddressRepository .

La clase / método de extensión le permite convertir una entidad a un modelo. Esto puede ser IQueryable o cualquier otra lista, colección .

Ahora viene la magia: si ha ejecutado la consulta ANTES de llamar a la extensión SelectOrderModel() , includeRelations dentro de la extensión será verdadera porque la source NO es un tipo de consulta de base de datos (no es un IQueryable de linq-to-sql). Cuando esto es cierto, la extensión puede llamar a otros métodos / extensiones a través de su aplicación para convertir modelos.

Ahora en el otro lado: primero puede ejecutar la extensión y luego continuar con el filtrado LINQ. El filtrado ocurrirá en la base de datos con el tiempo , porque aún no hizo una .ToList() , la extensión es solo una capa para tratar sus consultas. Linq-to-sql finalmente sabrá qué filtrado aplicar en la base de datos. Las inlcudeRelations serán falsas para que no llame a otros métodos de c # que SQL no comprende.

Parece complicado al principio, las extensiones pueden ser algo nuevo, pero es realmente útil. Finalmente, cuando haya configurado esto para todos los repositorios, simplemente un .Include() extra cargará las relaciones.