private IQueryable <dynamic> Sort(IQueryable <dynamic> data, SortInfo sortInfo) { if (!String.IsNullOrEmpty(sortInfo.SortColumn) || ((DefaultSort != null) && !String.IsNullOrEmpty(DefaultSort.SortColumn))) { return(Sort(data, _elementType, sortInfo)); } return(data); }
public IList <GenericWebGridRow> GetRows(SortInfo sortInfo, int pageIndex) { IEnumerable <dynamic> rowData = _values; if (_canSort) { rowData = Sort(_values.AsQueryable(), sortInfo); } rowData = Page(rowData, pageIndex); try { // Force compile the underlying IQueryable rowData = rowData.ToList(); } catch (ArgumentException) { // The OrderBy method uses a generic comparer which fails when the collection contains 2 or more // items that cannot be compared (e.g. DBNulls, mixed types such as strings and ints et al) with the exception // System.ArgumentException: At least one object must implement IComparable. // Silently fail if this exception occurs and declare that the two items are equivalent rowData = Page(_values.AsQueryable(), pageIndex); } return(rowData.Select((value, index) => new GenericWebGridRow(_grid, value: value, rowIndex: index)).ToList()); }
public IList <GenericWebGridRow> GetRows(SortInfo sortInfo, int pageIndex) { // Data is already sorted and paged. Ignore parameters. return(_rows); }
private IQueryable <dynamic> Sort(IQueryable <dynamic> data, Type elementType, SortInfo sort) { Debug.Assert(data != null); if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(elementType)) { // IDynamicMetaObjectProvider properties are only available through a runtime binder, so we // must build a custom LINQ expression for getting the dynamic property value. // Lambda: o => o.Property (where Property is obtained by runtime binder) // NOTE: lambda must not use internals otherwise this will fail in partial trust when Helpers assembly is in GAC var binder = Binder.GetMember( CSharpBinderFlags.None, sort.SortColumn, typeof(WebGrid), new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) } ); var param = Expression.Parameter(typeof(IDynamicMetaObjectProvider), "o"); var getter = Expression.Dynamic(binder, typeof(object), param); return(SortGenericExpression <IDynamicMetaObjectProvider, object>( data, getter, param, sort.SortDirection )); } Expression sorterFunctionBody; ParameterExpression sorterFunctionParameter; Expression sorter; if (_grid.CustomSorters.TryGetValue(sort.SortColumn, out sorter)) { var lambda = sorter as LambdaExpression; Debug.Assert(lambda != null); sorterFunctionBody = lambda.Body; sorterFunctionParameter = lambda.Parameters[0]; } else { // The IQueryable<dynamic> data source is cast as IQueryable<object> at runtime. We must call // SortGenericExpression using reflection so that the LINQ expressions use the actual element type. // Lambda: o => o.Property[.NavigationProperty,etc] sorterFunctionParameter = Expression.Parameter(elementType, "o"); Expression member = sorterFunctionParameter; var type = elementType; var sorts = sort.SortColumn.Split('.'); foreach (var name in sorts) { PropertyInfo prop = type.GetProperty(name); if (prop == null) { // no-op in case navigation property came from querystring (falls back to default sort) if ( (DefaultSort != null) && !sort.Equals(DefaultSort) && !String.IsNullOrEmpty(DefaultSort.SortColumn) ) { return(Sort(data, elementType, DefaultSort)); } return(data); } member = Expression.Property(member, prop); type = prop.PropertyType; } sorterFunctionBody = member; } var actualSortMethod = SortGenericExpressionMethod.MakeGenericMethod( elementType, sorterFunctionBody.Type ); return((IQueryable <dynamic>)actualSortMethod.Invoke( null, new object[] { data, sorterFunctionBody, sorterFunctionParameter, sort.SortDirection } )); }