Skip to content

Commit 0e221d1

Browse files
author
Mesut Talebi
committed
Added Dynamic Sort
1 parent 387aaed commit 0e221d1

File tree

7 files changed

+149
-90
lines changed

7 files changed

+149
-90
lines changed

mesoft.gridview/Content/gridview/megridview.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
megridview v0.3.3
2+
megridview v0.4.0
33
Developed By Mesut Talebi (mesut.talebi@yahoo.com)
44
Open Source And no licence :) free to use
55
*/

mesoft.gridview/HtmlHelpers/GridviewHelper.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
using System;
1+
// megridview v0.4.0
2+
// Developed By Mesut Talebi(mesut.talebi @yahoo.com)
3+
// Open Source And no licence :) free to use
4+
5+
using System;
26
using System.Web.Mvc;
37

48
namespace MT.GridView.HtmlHelpers
@@ -53,7 +57,7 @@ public static MvcHtmlString GridView(this HtmlHelper html, string readUrl, strin
5357
gridviewViewport.AddCssClass("gridview-viewport");
5458
gridviewViewport.Attributes.Add("id", "viewport");
5559
gridviewViewport.Attributes.Add("data-getdata-function", readUrl);
56-
gridviewViewport.InnerHtml+= @"<div class=""gridview-canvas"" style=""min-height:400px;"">
60+
gridviewViewport.InnerHtml+= @"<div class=""gridview-canvas table-responsive"" style=""min-height:400px;"">
5761
</div>
5862
<div class=""loading gridview-loader"">
5963
<img src = ""/images/loading.gif"" />

mesoft.gridview/Models/CustomersViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace MT.GridView.Models
77
{
88
public class CustomersViewModel
99
{
10-
public IQueryable<Customer> Customers { get; set; }
10+
public IEnumerable<Customer> Customers { get; set; }
1111

1212
public string JsonPagingInfo { get; set; }
1313
}

mesoft.gridview/Models/GridViewModelProvider.cs

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,19 @@ internal static CustomersViewModel GetCustomersViewModel(MyDbContext db, PagingI
3434
return model;
3535
}
3636

37-
private static IQueryable<Customer> GetData(IQueryable<Customer> Customers, PagingInfo PagingData, out int TotalItems)
37+
private static IEnumerable<Customer> GetData(IQueryable<Customer> customers, PagingInfo pagingData, out int totalItems)
3838
{
39-
var customers = Customers;
40-
4139
//search
42-
if (!string.IsNullOrEmpty(PagingData.SearchTerm))
40+
if (!string.IsNullOrEmpty(pagingData.SearchTerm))
4341
{
44-
customers = customers.Where(x => (x.CompanyName.Contains(PagingData.SearchTerm) || x.ContactTitle.Contains(PagingData.SearchTerm)));
42+
customers = customers.Where(x => (x.CompanyName.Contains(pagingData.SearchTerm)
43+
|| x.ContactTitle.Contains(pagingData.SearchTerm)));
4544
}
4645

4746
//filter
48-
if (PagingData.Filters != null)
47+
if (pagingData.Filters != null)
4948
{
50-
foreach (var filterObj in PagingData.Filters)
49+
foreach (var filterObj in pagingData.Filters)
5150
{
5251
switch (filterObj.Column)
5352
{
@@ -61,44 +60,17 @@ private static IQueryable<Customer> GetData(IQueryable<Customer> Customers, Pagi
6160
}
6261
}
6362

64-
65-
TotalItems = customers.Count();
63+
totalItems = customers.Count();
6664

6765
//sort
6866
customers = customers.OrderBy(x => x.Id);
69-
if (PagingData.Sort != null)
70-
{
71-
switch (PagingData.Sort.Direction)
72-
{
73-
case SortDirection.Ascending:
74-
if (PagingData.Sort.SortColumn == "CompanyName")
75-
{
76-
customers = customers.OrderBy(x => x.CompanyName);
77-
}
78-
else if (PagingData.Sort.SortColumn == "ContactTitle")
79-
{
80-
customers = customers.OrderBy(x => x.ContactTitle);
81-
}
82-
break;
83-
case SortDirection.Descending:
84-
if (PagingData.Sort.SortColumn == "CompanyName")
85-
{
86-
customers = customers.OrderByDescending(x => x.CompanyName);
87-
}
88-
else if (PagingData.Sort.SortColumn == "ContactTitle")
89-
{
90-
customers = customers.OrderByDescending(x => x.ContactTitle);
91-
}
92-
break;
93-
case SortDirection.NotSet:
94-
default:
95-
break;
96-
}
97-
}
67+
68+
customers = customers.Sort(pagingData.Sort);
69+
9870
customers = customers
99-
.Skip((PagingData.CurrentPage - 1) * PagingData.ItemsPerPage).Take(PagingData.ItemsPerPage);
71+
.Skip((pagingData.CurrentPage - 1) * pagingData.ItemsPerPage).Take(pagingData.ItemsPerPage);
10072

101-
return customers;
73+
return customers.ToList();
10274
}
10375
}
10476
}

mesoft.gridview/Models/GridviewModel.cs

Lines changed: 119 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
/*
2-
megridview v0.3.1
2+
megridview v0.4.0
33
Developed By Mesut Talebi (mesut.talebi@yahoo.com)
44
Open Source And no licence :) free to use
55
*/
66

77

88
using System;
99
using System.Collections.Generic;
10+
using System.Linq;
11+
using System.Linq.Expressions;
12+
using System.Reflection;
1013

1114
namespace MT.GridView.Models
1215
{
@@ -22,7 +25,7 @@ public class PagingInfo
2225

2326
public int TotalPages
2427
{
25-
get { return (int)Math.Ceiling((decimal)TotalItems / (ItemsPerPage != 0 ? ItemsPerPage : 1)); }
28+
get { return (int)Math.Ceiling((decimal)TotalItems / ( ItemsPerPage != 0 ? ItemsPerPage : 1 )); }
2629
}
2730

2831
public SortObject Sort { get; set; }
@@ -41,7 +44,7 @@ public class SortObject
4144

4245
public class FilterObject
4346
{
44-
public string Column { get; set; }
47+
public string Column { get; set; }
4548

4649
public string Value { get; set; }
4750

@@ -78,60 +81,156 @@ public enum FilterConjunction
7881
Or
7982
}
8083

81-
public class Extensions
84+
public static class Extensions
8285
{
86+
private static LambdaExpression GetExpression<T>(string propertyName, string methodName, out Type type)
87+
{
88+
string[] props = propertyName.Split('.');
89+
type = typeof(T);
90+
91+
ParameterExpression arg = Expression.Parameter(type, "x");
92+
Expression expr = arg;
93+
94+
foreach (string prop in props)
95+
{
96+
// use reflection (not ComponentModel) to mirror LINQ
97+
PropertyInfo pi = type.GetProperty(prop);
98+
expr = Expression.Property(expr, pi);
99+
type = pi.PropertyType;
100+
}
101+
102+
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
103+
104+
return Expression.Lambda(delegateType, expr, arg);
105+
}
106+
107+
private static IOrderedEnumerable<T> ApplyOrder<T>(
108+
IEnumerable<T> source,
109+
string propertyName,
110+
string methodName)
111+
{
112+
Type type = typeof(T);
113+
LambdaExpression lambda = GetExpression<T>(propertyName, methodName, out type);
114+
115+
object result = typeof(Queryable).GetMethods().Single(
116+
method => method.Name == methodName
117+
&& method.IsGenericMethodDefinition
118+
&& method.GetGenericArguments().Length == 2
119+
&& method.GetParameters().Length == 2)
120+
.MakeGenericMethod(typeof(T), type)
121+
.Invoke(null, new object[] { source, lambda });
122+
123+
return (IOrderedEnumerable<T>)result;
124+
}
125+
126+
127+
private static IOrderedQueryable<T> ApplyOrder<T>(
128+
IQueryable<T> source,
129+
string propertyName, string methodName)
130+
{
131+
Type type = typeof(T);
132+
LambdaExpression lambda = GetExpression<T>(propertyName, methodName, out type);
133+
134+
object result = typeof(Queryable).GetMethods().Single(
135+
method => method.Name == methodName
136+
&& method.IsGenericMethodDefinition
137+
&& method.GetGenericArguments().Length == 2
138+
&& method.GetParameters().Length == 2)
139+
.MakeGenericMethod(typeof(T), type)
140+
.Invoke(null, new object[] { source, lambda });
141+
142+
return (IOrderedQueryable<T>)result;
143+
}
144+
145+
// IQueryable Sort Extention
146+
public static IOrderedQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, SortObject sortObject)
147+
{
148+
if (sortObject != null)
149+
{
150+
switch (sortObject.Direction)
151+
{
152+
case SortDirection.Ascending:
153+
return ApplyOrder<TSource>(source, sortObject.SortColumn, "OrderBy");
154+
case SortDirection.Descending:
155+
return ApplyOrder<TSource>(source, sortObject.SortColumn, "OrderByDescending");
156+
default:
157+
break;
158+
}
159+
}
160+
161+
return source as IOrderedQueryable<TSource>;
162+
}
163+
164+
public static IOrderedEnumerable<TSource> Sort<TSource>(this IEnumerable<TSource> source, SortObject sortObject)
165+
{
166+
if (sortObject != null)
167+
{
168+
switch (sortObject.Direction)
169+
{
170+
case SortDirection.Ascending:
171+
return ApplyOrder<TSource>(source, sortObject.SortColumn, "OrderBy");
172+
case SortDirection.Descending:
173+
return ApplyOrder<TSource>(source, sortObject.SortColumn, "OrderByDescending");
174+
default:
175+
break;
176+
}
177+
}
178+
179+
return source as IOrderedEnumerable<TSource>;
180+
}
181+
83182
public static string GetWhereClause(FilterObject filterObj, Type valueType)
84-
{
183+
{
85184
string whereClause = "true";
86-
if (valueType != typeof (DateTime))
185+
if (valueType != typeof(DateTime))
87186
{
88187
switch (filterObj.Operator)
89188
{
90189
case FilterOperator.Contains:
91-
if (valueType == typeof (string))
190+
if (valueType == typeof(string))
92191
whereClause += string.Format(" {0} {1}.Contains(\"{2}\")", filterObj.Conjunction,
93192
filterObj.Column, filterObj.Value);
94193
break;
95194
case FilterOperator.GreaterThan:
96-
if (valueType != typeof (string))
195+
if (valueType != typeof(string))
97196
whereClause += string.Format(" {0} {1} > {2}", filterObj.Conjunction, filterObj.Column,
98197
filterObj.Value);
99198
break;
100199
case FilterOperator.GreaterThanOrEqual:
101-
if (valueType != typeof (string))
200+
if (valueType != typeof(string))
102201
whereClause += string.Format(" {0} {1} >= {2}", filterObj.Conjunction, filterObj.Column,
103202
filterObj.Value);
104203
break;
105204
case FilterOperator.LessThan:
106-
if (valueType != typeof (string))
205+
if (valueType != typeof(string))
107206
whereClause += string.Format(" {0} {1} < {2}", filterObj.Conjunction, filterObj.Column,
108207
filterObj.Value);
109208
break;
110209
case FilterOperator.LessThanOrEqual:
111-
if (valueType != typeof (string))
210+
if (valueType != typeof(string))
112211
whereClause += string.Format(" {0} {1} <= {2}", filterObj.Conjunction, filterObj.Column,
113212
filterObj.Value);
114213
break;
115214
case FilterOperator.StartsWith:
116-
if (valueType != typeof (string))
215+
if (valueType != typeof(string))
117216
whereClause += string.Format(" {0} {1}.StartsWith(\"{2}\")", filterObj.Conjunction,
118217
filterObj.Column, filterObj.Value);
119218
break;
120219
case FilterOperator.EndsWith:
121-
if (valueType != typeof (string))
220+
if (valueType != typeof(string))
122221
whereClause += string.Format(" {0} {1}.EndsWith(\"{2}\")", filterObj.Conjunction,
123222
filterObj.Column, filterObj.Value);
124223
break;
125224
case FilterOperator.Equals:
126225

127226
whereClause +=
128-
string.Format(valueType == typeof (string) ? " {0} {1} == \"{2}\"" : " {0} {1} == {2}",
227+
string.Format(valueType == typeof(string) ? " {0} {1} == \"{2}\"" : " {0} {1} == {2}",
129228
filterObj.Conjunction, filterObj.Column, filterObj.Value);
130229
break;
131230
case FilterOperator.NotEqual:
132231

133232
whereClause +=
134-
string.Format(valueType == typeof (string) ? " {0} {1} != \"{2}\"" : " {0} {1} != {2}",
233+
string.Format(valueType == typeof(string) ? " {0} {1} != \"{2}\"" : " {0} {1} != {2}",
135234
filterObj.Conjunction, filterObj.Column, filterObj.Value);
136235
break;
137236
default:
@@ -145,11 +244,11 @@ public static string GetWhereClause(FilterObject filterObj, Type valueType)
145244

146245
switch (filterObj.Operator)
147246
{
148-
case FilterOperator.Contains:
247+
case FilterOperator.Contains:
149248
break;
150249
case FilterOperator.GreaterThan:
151-
152-
whereClause += string.Format(" {0} {1} > DateTime(\"{2}\")", filterObj.Conjunction, filterObj.Column, dt);
250+
251+
whereClause += string.Format(" {0} {1} > DateTime(\"{2}\")", filterObj.Conjunction, filterObj.Column, dt);
153252
break;
154253
case FilterOperator.GreaterThanOrEqual:
155254

@@ -162,9 +261,9 @@ public static string GetWhereClause(FilterObject filterObj, Type valueType)
162261
case FilterOperator.LessThanOrEqual:
163262
whereClause += string.Format(" {0} {1} <= DateTime(\"{2}\")", filterObj.Conjunction, filterObj.Column, dt);
164263
break;
165-
case FilterOperator.StartsWith:
264+
case FilterOperator.StartsWith:
166265
break;
167-
case FilterOperator.EndsWith:
266+
case FilterOperator.EndsWith:
168267
break;
169268
case FilterOperator.Equals:
170269
whereClause += string.Format(" {0} {1} == DateTime(\"{2}\")", filterObj.Conjunction, filterObj.Column, dt);

mesoft.gridview/Scripts/gridview/megridview.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
megridview v0.3.3
2+
megridview v0.4.0
33
Developed By Mesut Talebi (mesut.talebi@yahoo.com)
44
Open Source And no licence :) free to use
55
*/
@@ -348,7 +348,7 @@
348348
$('th.sortable > span', obj).removeClass('fa-chevron-up').removeClass('fa-chevron-down');
349349

350350
//find sorted column
351-
var sortableTh = $('th.sortable[data-sort=' + $gridviewObject.Sort.SortColumn + ']', obj);
351+
var sortableTh = $('th.sortable[data-sort="' + $gridviewObject.Sort.SortColumn + '"]', obj);
352352
console.log(sortableTh);
353353

354354
$(sortableTh).addClass('sorted');

mesoft.gridview/Views/Home/_CustomersPartial.cshtml

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,14 @@
66
<table class="table table-bordered table-striped">
77
<thead>
88
<tr class="gridview-list-header">
9-
<th>
10-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Id))
11-
</th>
12-
<th class="sortable" data-sort="CompanyName">
13-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().CompanyName))
14-
</th>
15-
<th class="sortable" data-sort="ContactTitle">
16-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().ContactTitle))
17-
</th>
18-
<th>
19-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Country))
20-
</th>
21-
<th>
22-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().City))
23-
</th>
24-
<th>
25-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Address))
26-
</th>
27-
<th>
28-
@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Phone))
29-
</th>
30-
<th>
31-
@Html.DisplayNameFor(x=> x.Customers.FirstOrDefault().Founded)
32-
</th>
9+
<th>@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Id))</th>
10+
<th class="sortable" data-sort="CompanyName">@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().CompanyName))</th>
11+
<th class="sortable" data-sort="ContactTitle">@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().ContactTitle))</th>
12+
<th class="sortable" data-sort="Country">@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Country))</th>
13+
<th class="sortable" data-sort="City">@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().City))</th>
14+
<th>@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Address))</th>
15+
<th>@(Html.DisplayNameFor(x => x.Customers.FirstOrDefault().Phone))</th>
16+
<th class="sortable" data-sort="Founded">@Html.DisplayNameFor(x=> x.Customers.FirstOrDefault().Founded)</th>
3317
</tr>
3418
</thead>
3519

0 commit comments

Comments
 (0)