Custom Sort Order

Developer
Jun 1, 2011 at 6:33 PM

Until there is a way to enable custom sort orders in the API I thought I would include my work around. Basically, in the controller method I check the searchModel.SortColumnName to see if it contains a column that needs a custom order, and applies the order before giving it to the grid. I am sure there is a better way to write this, but it works for my needs. Here is the example:

 

    public ActionResult List(SearchModel searchModel)
        {
            IEnumerable<Member> memberEntities = null;
            
            ApplyCustomSort(ref searchModel, ref memberEntities);
            
            
            IEnumerable<MemberModel> members =
                _presentationMapper.Map<IEnumerable<Member>, IEnumerable<MemberModel>>(memberEntities);

            IQueryable<MemberModel> model = members.AsQueryable();

            
           
            GridData gridData = model.ToGridData(searchModel);
            
            return Json(gridData, JsonRequestBehavior.AllowGet);

        }

        private void ApplyCustomSort(ref SearchModel searchModel, ref IEnumerable<Member> memberEntities)
        {
            if (searchModel.SortColumnName == "Rank")
            {
                if (searchModel.SortOrder == "asc")
                {
                    memberEntities = _membersServices.GetAllMembers().OrderBy(o => o.Rank.RankID);
                }
                else
                {
                    memberEntities = _membersServices.GetAllMembers().OrderByDescending(o => o.Rank.RankID);
                }
                searchModel.SortColumnName = "";
                searchModel.SortOrder = "";

            }
            else
            {
                memberEntities = _membersServices.GetAllMembers();
            }
        }

Coordinator
Jun 1, 2011 at 6:53 PM

Basically, the idea of being able to add custom predicates to the filtering\sorting mechanism can be very usefull,

but I'll need to think about it to see if there's a way to be better integrate it into the process. (perhaps inside the searchModel's ApplyFilters method)

Thanks for the idea and workaround!

Developer
Jun 1, 2011 at 8:41 PM
Edited Jun 1, 2011 at 8:43 PM

For those interested, here is a way to do it with the jqGrid/MCjQueryControls API.

There is a property in the jqGrid colModel API called sorttype where you would specify the type of sorting to be done (Ie string, date, number). If you just want to change to one of those, the API has the .SetCellType method on the GridColumnModel. If you want a custom sort order though, you can define a function for this property.

However the sorttype only works for local data (ie all the data is sent on the first loading of the page) This took me a while to find out :)

So if your data is small enough that you don't mind sending it all at once, then you can do custom sorting on the client side.

Here is how.

First make your data local. To do this, you have to pass the data into a variable in the ViewData array. This is done on the controller that returns the view.

 

 public ActionResult Index()
        {

            IEnumerable<Member> memberEntities = _membersServices.GetAllMembers();
            IEnumerable<MemberModel> members = _presentationMapper.Map<IEnumerable<Member>, IEnumerable<MemberModel>>(memberEntities);

            MembersViewModel membersViewModel = new MembersViewModel() { Members = members };
            ViewData["GridDataSource"] = members;
            return View(membersViewModel);
        }

 

Then you need to define your sort function. You can do it by hand:

 

StringBuilder sortFunction = new StringBuilder();
    sortFunction.AppendLine("sorttype:");
    sortFunction.AppendLine("function(cellValue, rowObject)");
    sortFunction.AppendLine("{");
    sortFunction.AppendLine("if (cellValue=='RankHighest') return 0;");
    sortFunction.AppendLine("if (cellValue=='RankMiddle') return 1;");
    sortFunction.AppendLine("if (cellValue=='RankLowest') return 2;");
    sortFunction.AppendLine("return 4;");
    sortFunction.AppendLine("}");

 

Or if you have a sort order in your data already, you can include it in griddata and use it to sort, in my case, RankID:

 

    StringBuilder sortFunction = new StringBuilder();
    sortFunction.AppendLine("sorttype:");
    sortFunction.AppendLine("function(cellValue, rowObject)");
    sortFunction.AppendLine("{");
    sortFunction.AppendLine("return rowObject.RankID;");
    sortFunction.AppendLine("}");

Finally, the grid. I want to do my custom sort on the Rank column, so I add my custom property there.
 @Html.Grid(new GridControl()
            .SetName("grid")
            .SetPageSize(40)
            .SetIsAutoSize(true)
            .SetDataSource(ViewData["GridDataSource"])
            .SetColumns<Website.Models.MemberModels.MemberModel>(cs =>
                {
                    cs.Add(x => x.MemberID).SetAsPrimaryKey().SetHidden(true);
                    cs.Add(x => x.SN);
                    cs.Add(x => x.Rank).SetCustomAttributes(sortFunction.ToString());
                    cs.Add(x => x.LastName);
                    cs.Add(x => x.Initials);
                    cs.Add(x => x.Supervisor);
                    cs.Add(x => x.Instrument);
                    cs.Add(x => x.Effective);
                    cs.Add(x => x.AdminStatus);

                })
            );

 

Notice that I did not include RankID in my column list. All data is passed to the grid regardless if it is in the column list. But because it is not in the column list, it is not displayed.

Hope this helps!