Reputation: 7444
Say I have a view model for a list view that renders a table.
View Model:
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;}
}
View:
<th>@Html.DisplayNameFor(model => model.Documents[0].Name)</th>
<th>@Html.DisplayNameFor(model => model.Documents[0].Age)</th>
Controller:
public ActionResult Index(SortModel model)
{
var docs = db.GetDocs();
if(model.SortParameter == "Age" && model.SortOrder == "desc")
{
docs.OrderByDescending(x => x.Age);
}
return View(model);
}
How can I render the View so that the table headers are clickable and will update the model before posting? I want to avoid using ViewBag.
I'm guessing I'll need to use an ActionLink, but I'm not sure how to update the model before posting.
Something like:
<th>@Html.ActionLink("Index", "Home", "Name", new { Model.SortParameter = "Name", Model.SortOrder = "Desc"})
Upvotes: 1
Views: 2835
Reputation:
Change you table headers to
<th>@Html.ActionLink("Name", "Index", "Home", new { SortParameter = "Name", SortOrder = Model.SortOrder }, null)</th>
<th>@Html.ActionLink("Name", "Index", "Home", new { SortParameter = "Age", SortOrder = Model.SortOrder }, null)</th>
and then modify the controller method to toggle the SortOrder
public ActionResult Index(SortModel model)
{
var docs = db.GetDocs();
if(model.SortParameter == "Age" && model.SortOrder == "desc")
{
docs.OrderByDescending(x => x.Age);
model.SortOrder == "acs"
}
return View(model);
}
Note it would probably be easier if you had a bool IsAscending
property rather than your string SortOrder
.
However, you only have one 'SortOrder' property, so if the current view is displaying the Documents sorted by Name
in ascending order, and the user clicks on Age
, then the Documents will be sorted by Age
in ascending order. If the user then clicks on Name
, the Documents will be sorted by Name
in descending order. You have not stated why the desired behavior is, but you could add multiple 'SortOrder' properties, say
public bool IsNameAscending { get; set; }
public bool IsAgeAscending { get; set; }
to handle that, and also to allow you to use a .ThenBy()
in your query, for example
docs.OrderBy(x => x.Age).ThenBy(x=> x.Name);
You might also want to render a visual indicator (e.g. up or down arrows) to indicate the current sort order to the user.
Upvotes: 2