Alright, I've fixed up Customers and here is what I did. Note I did not make all columns sortable (Id and Edit primarily, along with the checkbox column). All the others do sort appropriately. Here we go.
In Libraries\Nop.Core\Domain\Customers, add CustomerSortingEnum.cs
namespace Nop.Core.Domain.Customers
{
public enum CustomerSortingEnum
{
/// <summary>
/// Default
/// Created On: Most recent to earliest
/// </summary>
CreatedOnDsc = 0,
/// <summary>
/// Created On: Earliest to most recent
/// </summary>
CreatedOnAsc = 1,
/// <summary>
/// UserName: A to Z
/// </summary>
UserNameAsc = 2,
/// <summary>
/// UserName: Z to A
/// </summary>
UserNameDesc = 3,
/// <summary>
/// Name: A to Z
/// </summary>
CustomerNameAsc = 4,
/// <summary>
/// Name: Z to A
/// </summary>
CustomerNameDesc = 5,
/// <summary>
/// Unit: A to Z
/// </summary>
UnitAsc = 6,
/// <summary>
/// Unit: Z to A
/// </summary>
UnitDesc = 7,
/// <summary>
/// Customer Role: A to Z
/// </summary>
CustomerRolesAsc = 8,
/// <summary>
/// Customer Role: Z to A
/// </summary>
CustomerRolesDesc = 9,
/// <summary>
/// Active: False to frue
/// </summary>
ActiveAsc = 10,
/// <summary>
/// Active: True to false
/// </summary>
ActiveDesc = 11,
/// <summary>
/// Last Activity: Earliest to most recent
/// </summary>
LastActivityAsc = 12,
/// <summary>
/// Last Activity: Most recent to earliest
/// </summary>
LastActivityDesc = 13,
}
}
In Libraries\Nop.Services\Customers\CustomerService.cs, change the GetAllCustomers method to match this.
public virtual IPagedList<Customer> GetAllCustomers(DateTime? registrationFrom,
DateTime? registrationTo, int[] customerRoleIds, string email, string username,
string firstName, string lastName, int dayOfBirth, int monthOfBirth,
string company, string phone, string zipPostalCode,
bool loadOnlyWithShoppingCart, ShoppingCartType? sct, CustomerSortingEnum sortOrder, int pageIndex, int pageSize)
{
... (around the bottom where there is an OrderBy, replace it with this code)
//Sort data
query = SortData(sortOrder, query);
var customers = new PagedList<Customer>(query, pageIndex, pageSize);
return customers;
}
private IQueryable<Customer> SortData(CustomerSortingEnum sortOrder, IQueryable<Customer> customers)
{
//Temporary list for dealing with certain columns
var tempCustomers = new List<Customer>();
//Dictionary of Customers
var customerDictionary = new Dictionary<int, string>();
//Switch statement on Sort Order for grid
switch (sortOrder)
{
case CustomerSortingEnum.CreatedOnDsc:
customers = customers.OrderByDescending(c => c.CreatedOnUtc);
break;
case CustomerSortingEnum.CreatedOnAsc:
customers = customers.OrderBy(c => c.CreatedOnUtc);
break;
case CustomerSortingEnum.UserNameAsc:
customers = customers.OrderBy(c => c.Username);
break;
case CustomerSortingEnum.UserNameDesc:
customers = customers.OrderByDescending(c => c.Username);
break;
case CustomerSortingEnum.CustomerNameAsc:
//Create a dictionary with the Id and Full Name of a Customer
foreach (var customer in customers)
{
customerDictionary.Add(customer.Id, customer.GetFullName());
}
//Order the dictionary ascending by Full Name
customerDictionary = customerDictionary.OrderBy(cd => cd.Value).ToDictionary(cd => cd.Key, cd => cd.Value);
//Build a new list of Customers ordered correctly
foreach (var item in customerDictionary)
{
var customer = customers.Where(c => c.Id == item.Key).FirstOrDefault();
tempCustomers.Add(customer);
}
//Repopulate the primary list with the sorted Customers
customers = tempCustomers.AsQueryable();
break;
case CustomerSortingEnum.CustomerNameDesc:
//Create a dictionary with the Id and Full Name of a Customer
foreach (var customer in customers)
{
customerDictionary.Add(customer.Id, customer.GetFullName());
}
//Order the dictionary descending by Full Name
customerDictionary = customerDictionary.OrderByDescending(cd => cd.Value).ToDictionary(cd => cd.Key, cd => cd.Value);
//Build a new list of Customers ordered correctly
foreach (var item in customerDictionary)
{
var customer = customers.Where(c => c.Id == item.Key).FirstOrDefault();
tempCustomers.Add(customer);
}
//Repopulate the primary list with the sorted Customers
customers = tempCustomers.AsQueryable();
break;
case CustomerSortingEnum.UnitAsc:
customers = customers.OrderBy(c => c.Unit);
break;
case CustomerSortingEnum.UnitDesc:
customers = customers.OrderByDescending(c => c.Unit);
break;
case CustomerSortingEnum.CustomerRolesAsc:
foreach (var customer in customers)
{
var roles = string.Empty;
foreach (var customerRole in customer.CustomerRoles)
{
roles += customerRole.Name + ", ";
}
roles = roles.Remove(roles.Length - 2);
customerDictionary.Add(customer.Id, roles);
}
customerDictionary = customerDictionary.OrderBy(cd => cd.Value).ToDictionary(cd => cd.Key, cd => cd.Value);
foreach (var item in customerDictionary)
{
var customer = customers.Where(c => c.Id == item.Key).FirstOrDefault();
tempCustomers.Add(customer);
}
customers = tempCustomers.AsQueryable();
break;
case CustomerSortingEnum.CustomerRolesDesc:
foreach (var customer in customers)
{
var roles = string.Empty;
foreach (var customerRole in customer.CustomerRoles)
{
roles += customerRole.Name + ", ";
}
roles = roles.Remove(roles.Length - 2);
customerDictionary.Add(customer.Id, roles);
}
customerDictionary = customerDictionary.OrderByDescending(cd => cd.Value).ToDictionary(cd => cd.Key, cd => cd.Value);
foreach (var item in customerDictionary)
{
var customer = customers.Where(c => c.Id == item.Key).FirstOrDefault();
tempCustomers.Add(customer);
}
customers = tempCustomers.AsQueryable();
break;
case CustomerSortingEnum.ActiveAsc:
customers = customers.OrderBy(c => c.Active);
break;
case CustomerSortingEnum.ActiveDesc:
customers = customers.OrderByDescending(c => c.Active);
break;
case CustomerSortingEnum.LastActivityAsc:
customers = customers.OrderBy(c => c.LastActivityDateUtc);
break;
case CustomerSortingEnum.LastActivityDesc:
customers = customers.OrderByDescending(c => c.LastActivityDateUtc);
break;
default:
customers = customers.OrderByDescending(c => c.CreatedOnUtc);
break;
}
return customers;
}
Slight change to ICustomerService.cs
IPagedList<Customer> GetAllCustomers(DateTime? registrationFrom,
DateTime? registrationTo, int[] customerRoleIds, string email, string username,
string firstName, string lastName, int dayOfBirth, int monthOfBirth,
string company, string phone, string zipPostalCode,
bool loadOnlyWithShoppingCart, ShoppingCartType? sct, CustomerSortingEnum sortOrder, int pageIndex, int pageSize);
View (List.cshtml)
@(Html.Telerik().Grid<CustomerModel>(Model.Customers.Data)
.Name("customers-grid")
.ClientEvents(events => events
.OnDataBinding("onDataBinding")
.OnDataBound("onDataBound"))
.Sortable()
.Columns(columns =>
{
columns.Bound(x => x.Id)
.Template(x => string.Format("<input type='checkbox' name='checkedRecords' value='{0}' class='checkboxGroups'/>", x.Id))
.ClientTemplate("<input type='checkbox' name='checkedRecords' value='<#= Id #>' class='checkboxGroups'/>")
.Title("<input id='mastercheckbox' type='checkbox'/>")
.Width(50)
.HtmlAttributes(new { style = "text-align:center" })
.HeaderHtmlAttributes(new { style = "text-align:center" })
.Sortable(false);
columns.Bound(x => x.Id)
.Width(50)
.Sortable(false);
//I don't know why but the customer list does not have an 'Edit' column in the grid on some machines (maybe because we are inside Html.BeginForm()).
//That's why the 'Email' column is clickable.
//columns.Bound(x => x.Email)
// .Template(x => Html.ActionLink(x.Email, "Edit", "Customer", new { id = x.Id }, new { }))
// .ClientTemplate("<a href=\"" + @Url.Content("~/Admin/Customer/Edit/") + "<#= Id #>\"><#= Email #></a>")
// .Width(150)
// .Sortable(false);
columns.Bound(x => x.Username)
.Width(150)
.Visible(Model.UsernamesEnabled);
columns.Bound(x => x.FullName)
.Width(200);
columns.Bound(x => x.Unit)
.Width(100);
columns.Bound(x => x.CustomerRoleNames)
.Width(200);
columns.Bound(x => x.Company)
.Width(150)
.Visible(Model.CompanyEnabled)
.Sortable(false);
columns.Bound(x => x.Phone)
.Width(100)
.Visible(Model.PhoneEnabled)
.Sortable(false);
columns.Bound(x => x.ZipPostalCode)
.Width(75)
.Visible(Model.ZipPostalCodeEnabled)
.Sortable(false);
columns.Bound(x => x.Active)
.Width(100)
.Template(x => x.Active.ToString().ToLower())
.Centered();
columns.Bound(x => x.CreatedOn)
.Width(100);
columns.Bound(x => x.LastActivityDate)
.Width(100);
columns.Bound(x => x.Id)
.Width(50)
.Centered()
.Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id }))
.ClientTemplate("<a href=\"Edit/<#= Id #>\">" + T("Admin.Common.Edit").Text + "</a>")
.Title(T("Admin.Common.Edit").Text)
.Sortable(false);
})
.Pageable(settings => settings.Total(Model.Customers.Total).PageSize(gridPageSize).Position(GridPagerPosition.Both))
.DataBinding(dataBinding => dataBinding.Ajax().Select("CustomerList", "Customer"))
.EnableCustomBinding(true))
CustomerController.cs
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult CustomerList(GridCommand command, CustomerListModel model)
{
...
//after last if statement, here is the new code
var sortOrder = GetSortOrder(command);
var customers = _customerService.GetAllCustomers(null, null,
model.SearchCustomerRoleIds, model.SearchEmail, model.SearchUsername,
model.SearchFirstName, model.SearchLastName,
searchDayOfBirth, searchMonthOfBirth,
model.SearchCompany, model.SearchPhone, model.SearchZipPostalCode,
false, null, sortOrder, command.Page - 1, command.PageSize);
...
}
//In Utilities, add this
[NonAction]
private CustomerSortingEnum GetSortOrder(GridCommand command)
{
if (command.SortDescriptors.Any())
{
var sortDescriptors = command.SortDescriptors.FirstOrDefault();
var sortOrder = new CustomerSortingEnum();
switch (sortDescriptors.Member)
{
case "Username":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.UserNameAsc : CustomerSortingEnum.UserNameDesc;
break;
case "FullName":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.CustomerNameAsc : CustomerSortingEnum.CustomerNameDesc;
break;
case "Unit":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.UnitAsc : CustomerSortingEnum.UnitDesc;
break;
case "CustomerRoleNames":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.CustomerRolesAsc : CustomerSortingEnum.CustomerRolesDesc;
break;
case "Active":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.ActiveAsc : CustomerSortingEnum.ActiveDesc;
break;
case "CreatedOn":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.CreatedOnAsc : CustomerSortingEnum.CreatedOnDsc;
break;
case "LastActivityDate":
sortOrder = sortDescriptors.SortDirection == 0 ? CustomerSortingEnum.LastActivityAsc : CustomerSortingEnum.LastActivityDesc;
break;
default:
sortOrder = CustomerSortingEnum.CreatedOnDsc;
break;
}
return sortOrder;
}
return CustomerSortingEnum.CreatedOnDsc;
}
Lastly, make sure you update all other references to GetAllCustomers with the new parameter. In those instances, you can use CustomerSortingEnum.CreatedOnDesc for the default value (what grid was normally sorted on).
Hope that helps and let me know if you need help. Cheers.