ASP.Net MVC 中的多选过滤分页视图
Multiselect filtering a paged view in ASP.Net MVC
在我的 MVC 5 "Index" 视图中,我使用了 paged list 并应用了过滤器,它们只是下拉列表,如下所示(按角色过滤用户列表)。
public ActionResult Index(int? roleId, int? page)
{
var pageNumber = page ?? 1;
var currentRoleId = roleId ?? 0;
var Roles = db.Roles.OrderBy(r => r.Name).ToList();
ViewBag.RoleId = new SelectList(Roles, "RoleId", "Name", currentRoleId);
var users = db.Users;
ViewBag.OnePageOfUsers = users.ToPagedList(pageNumber, 20);
在我看来,我有以下内容来捕获过滤器更改,
@Html.DropDownList("RoleId", null, new { onchange = "$(this.form).submit();" })
和以下内容以使用选定的 roleid
处理分页
@Html.PagedListPager((IPagedList)ViewBag.OnePageOfUsers,
page => Url.Action("Index", new
{
page,
roleId = ViewBag.RoleId.SelectedValue
}),
PagedListRenderOptions.ClassicPlusFirstAndLast)
一切正常,但现在我想使用多选列表(按多个角色筛选),我遇到了麻烦。我已经到了可以初始化所选角色并显示列表的地步,但是当我去更改过滤器选择时,我无法弄清楚如何将选择返回给控制器。经过反复试验,我的做法如下:
创建了一个视图模型来保存过滤器列表和选择。
public IEnumerable<int> SelectedRoleIds { get; set; }
public MultiSelectList Roles { get; set; }
在我的控制器中初始化我的 ViewModel...
public ActionResult Index(int ? page, int [] roles)
{
:
model.SelectedRoleIds = new int[] { 2, 3 };// just for testing
model.Roles = new MultiSelectList(RoleList, "RoleId", "Name", model.SelectedRoleIds);
在我看来,我现在有一个用于多选的列表框。
@Html.ListBoxFor(m => m.SelectedRoleIds, Model.Roles, new { multiple = "multiple", onchange = "$(this.form).submit();" })
在我看来,我尝试分配选择...
@Html.PagedListPager((IPagedList)ViewBag.OnePageOfUsers,
page => Url.Action("Index", new
{
page,
roles = Model.SelectedRoleIds
}),
PagedListRenderOptions.ClassicPlusFirstAndLast)
我的做法正确吗?我一直在兜圈子,有时让分页在没有过滤的情况下工作,反之亦然。我已经尝试了 POST 操作,但是我无法让分页工作。可能有更好的方法来实现我的目标。
总的来说,我的方法是正确的。我缺少的关键部分是将所选值从视图发送到控制器,这意味着将一个 int 数组(比如 x[] = {1,2,3})转换为查询参数 x=1&x=2&x=3 所以它可以传回。
这是我使用多选列表过滤 MVC 分页 list/index 视图的简化整体解决方案。
我的视图模型
public class UserViewModel
{
public int [] SelectedRoleIds { get; set; }
public MultiSelectList Roles { get; set; }
}
控制器动作
public ActionResult Index(int? page, string[] SelectedRoleIds)
{
UserViewModel model = new UserViewModel();
var users = db.Users;
var pageNumber = page ?? 1;
var RoleList = db.Roles;
model.Roles = new MultiSelectList(RoleList, "RoleId", "Name", model.SelectedRoleIds);
if (SelectedRoleIds != null)
model.SelectedRoleIds = Array.ConvertAll(SelectedRoleIds, int.Parse);
// Filter the users by role selection
if (model.SelectedRoleIds != null)
{
users = users.Where(a => model.SelectedRoleIds.All(requiredId => a.Roles.Any(role => role.RoleId == requiredId)));
}
ViewBag.OnePageOfUsers = users.ToPagedList(pageNumber, pagesize);
return View(model);
}
景色
@Html.ListBoxFor(m => m.SelectedRoleIds, Model.Roles, new { multiple = "multiple", onchange = "$(this.form).submit();" })
<a href="@Url.Action("Index")" class="btn btn-info btn-xs">Reset</a>
@Html.PagedListPager((IPagedList)ViewBag.OnePageOfUsers,
page => Url.Action("Index", new { page = page }) +
(Model.SelectedRoleIds == null ? "" : "&" + string.Join("&", ((int[])Model.SelectedRoleIds).Select(x => "SelectedRoleIds=" + Url.Encode(x.ToString())))))
在我的 MVC 5 "Index" 视图中,我使用了 paged list 并应用了过滤器,它们只是下拉列表,如下所示(按角色过滤用户列表)。
public ActionResult Index(int? roleId, int? page)
{
var pageNumber = page ?? 1;
var currentRoleId = roleId ?? 0;
var Roles = db.Roles.OrderBy(r => r.Name).ToList();
ViewBag.RoleId = new SelectList(Roles, "RoleId", "Name", currentRoleId);
var users = db.Users;
ViewBag.OnePageOfUsers = users.ToPagedList(pageNumber, 20);
在我看来,我有以下内容来捕获过滤器更改,
@Html.DropDownList("RoleId", null, new { onchange = "$(this.form).submit();" })
和以下内容以使用选定的 roleid
处理分页@Html.PagedListPager((IPagedList)ViewBag.OnePageOfUsers,
page => Url.Action("Index", new
{
page,
roleId = ViewBag.RoleId.SelectedValue
}),
PagedListRenderOptions.ClassicPlusFirstAndLast)
一切正常,但现在我想使用多选列表(按多个角色筛选),我遇到了麻烦。我已经到了可以初始化所选角色并显示列表的地步,但是当我去更改过滤器选择时,我无法弄清楚如何将选择返回给控制器。经过反复试验,我的做法如下:
创建了一个视图模型来保存过滤器列表和选择。
public IEnumerable<int> SelectedRoleIds { get; set; }
public MultiSelectList Roles { get; set; }
在我的控制器中初始化我的 ViewModel...
public ActionResult Index(int ? page, int [] roles)
{
:
model.SelectedRoleIds = new int[] { 2, 3 };// just for testing
model.Roles = new MultiSelectList(RoleList, "RoleId", "Name", model.SelectedRoleIds);
在我看来,我现在有一个用于多选的列表框。
@Html.ListBoxFor(m => m.SelectedRoleIds, Model.Roles, new { multiple = "multiple", onchange = "$(this.form).submit();" })
在我看来,我尝试分配选择...
@Html.PagedListPager((IPagedList)ViewBag.OnePageOfUsers,
page => Url.Action("Index", new
{
page,
roles = Model.SelectedRoleIds
}),
PagedListRenderOptions.ClassicPlusFirstAndLast)
我的做法正确吗?我一直在兜圈子,有时让分页在没有过滤的情况下工作,反之亦然。我已经尝试了 POST 操作,但是我无法让分页工作。可能有更好的方法来实现我的目标。
总的来说,我的方法是正确的。我缺少的关键部分是将所选值从视图发送到控制器,这意味着将一个 int 数组(比如 x[] = {1,2,3})转换为查询参数 x=1&x=2&x=3 所以它可以传回。
这是我使用多选列表过滤 MVC 分页 list/index 视图的简化整体解决方案。
我的视图模型
public class UserViewModel
{
public int [] SelectedRoleIds { get; set; }
public MultiSelectList Roles { get; set; }
}
控制器动作
public ActionResult Index(int? page, string[] SelectedRoleIds)
{
UserViewModel model = new UserViewModel();
var users = db.Users;
var pageNumber = page ?? 1;
var RoleList = db.Roles;
model.Roles = new MultiSelectList(RoleList, "RoleId", "Name", model.SelectedRoleIds);
if (SelectedRoleIds != null)
model.SelectedRoleIds = Array.ConvertAll(SelectedRoleIds, int.Parse);
// Filter the users by role selection
if (model.SelectedRoleIds != null)
{
users = users.Where(a => model.SelectedRoleIds.All(requiredId => a.Roles.Any(role => role.RoleId == requiredId)));
}
ViewBag.OnePageOfUsers = users.ToPagedList(pageNumber, pagesize);
return View(model);
}
景色
@Html.ListBoxFor(m => m.SelectedRoleIds, Model.Roles, new { multiple = "multiple", onchange = "$(this.form).submit();" })
<a href="@Url.Action("Index")" class="btn btn-info btn-xs">Reset</a>
@Html.PagedListPager((IPagedList)ViewBag.OnePageOfUsers,
page => Url.Action("Index", new { page = page }) +
(Model.SelectedRoleIds == null ? "" : "&" + string.Join("&", ((int[])Model.SelectedRoleIds).Select(x => "SelectedRoleIds=" + Url.Encode(x.ToString())))))