基于ViewModel实现MVC列表视图可点击表头排序(禁用ViewBag)
实现MVC表格表头点击排序(无需ViewBag)
嘿,我来帮你搞定这个表头排序的需求,完全不用ViewBag,就用你现有的SortModel就能实现。咱们一步步来:
首先,先修正你控制器里的小问题——你原来的排序代码只是生成了排序后的序列,但没把结果赋值回docs,而且只处理了Age降序的情况,咱们完善一下:
public ActionResult Index(SortModel model) { var docs = db.GetDocs().ToList(); // 先获取基础文档数据 // 处理排序逻辑 if (!string.IsNullOrEmpty(model.SortParameter)) { switch (model.SortParameter) { case "Age": docs = model.SortOrder == "desc" ? docs.OrderByDescending(x => x.Age).ToList() : docs.OrderBy(x => x.Age).ToList(); break; case "Name": docs = model.SortOrder == "desc" ? docs.OrderByDescending(x => x.Name).ToList() : docs.OrderBy(x => x.Name).ToList(); break; // 以后要加其他字段排序,直接在这里加case就行 } } else { // 设置默认排序:比如按Name升序 docs = docs.OrderBy(x => x.Name).ToList(); model.SortParameter = "Name"; model.SortOrder = "asc"; } model.Documents = docs; // 把排序后的数据赋值回ViewModel return View(model); }
接下来是视图部分,把原来的表头改成可点击的ActionLink,点击时自动传递SortParameter和SortOrder参数给控制器,更新ViewModel:
@{ // 写个小辅助方法,用来判断下一次点击的排序方向 string GetSortOrder(string currentParam, string targetParam, string currentOrder) { // 如果当前已经是按目标字段升序,就切换成降序,否则默认升序 return currentParam == targetParam && currentOrder == "asc" ? "desc" : "asc"; } } <table> <thead> <tr> <th> @Html.ActionLink( // 显示字段的DisplayName Html.DisplayNameFor(model => model.Documents[0].Name).ToString(), // 指向的Action方法 "Index", // 传递的参数,对应SortModel的属性 new { SortParameter = "Name", SortOrder = GetSortOrder(Model.SortParameter, "Name", Model.SortOrder) } ) <!-- 可选:显示当前排序方向的小箭头 --> @if (Model.SortParameter == "Name") { @(Model.SortOrder == "asc" ? " ↑" : " ↓") } </th> <th> @Html.ActionLink( Html.DisplayNameFor(model => model.Documents[0].Age).ToString(), "Index", new { SortParameter = "Age", SortOrder = GetSortOrder(Model.SortParameter, "Age", Model.SortOrder) } ) @if (Model.SortParameter == "Age") { @(Model.SortOrder == "asc" ? " ↑" : " ↓") } </th> </tr> </thead> <tbody> <!-- 遍历显示文档数据 --> @foreach (var item in Model.Documents) { <tr> <td>@Html.DisplayFor(modelItem => item.Name)</td> <td>@Html.DisplayFor(modelItem => item.Age)</td> </tr> } </tbody> </table>
你的ViewModel完全不用改,保持原来的结构就行:
public class SortModel { public List<Document> Documents { get; set; } public string SortParameter { get; set; } public string SortOrder { get; set; } } public class Document { public string Name { get; set; } public int Age { get; set; } }
原理很简单:点击表头的ActionLink时,会把对应的SortParameter(比如"Name"或"Age")和计算好的SortOrder(asc/desc)作为参数传递给Index控制器方法,控制器根据这两个参数对数据排序,再把排序后的数据赋值回ViewModel,最后返回视图刷新页面。
这样就完全不用ViewBag,所有状态都通过ViewModel来维护啦!
内容的提问来源于stack exchange,提问作者woggles
相关产品推荐
相关产品推荐

