SingingEels : Development Community & Resource

Login

Articles

  • ADO.NET (2)
  • ASP.NET (36)
  • LINQ (5)
  • Security (2)
  • Silverlight (3)
  • SQL (7)
  • Standards (5)
  • WCF (2)

Syndication

  • Articles RSS
  • Blogs RSS

Contribute

  • Our Authors List
  • Member Sign-Up
  • Suggestions Box

Follow up to Self Sorting GridView

(Mar 25 2009 - 05:16:29 PM by kiwipete) - [print blog post]

Some updates I made to

http://www.singingeels.com/Articles/Self_Sorting_GridView_with_LINQ_Expression_Trees.aspx

to allow Self Paging as well as sorting.

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Linq.Expressions;

using System.Reflection;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace SingingEels.Web.UI.WebControls

{

// SelfSortingGridView - GridView from www.singingeels.com

// Updated to allow paging as well as sorting.

public class LinqGridView : GridView

{

private string _lastSortExpression;

private SortDirection _lastSortDirection;

protected override void OnSorting(GridViewSortEventArgs e)

{

this.Sorting += new GridViewSortEventHandler(this.SelfSortingGridView_Sorting);

base.OnSorting(e);

}

private void SelfSortingGridView_Sorting(object sender, GridViewSortEventArgs e)

{

this.PageIndex = 0; // Go back to the start of the list on sorting.

if (e.SortExpression == this._lastSortExpression && this._lastSortDirection == SortDirection.Ascending)

{

e.SortDirection = SortDirection.Descending;

}

else

{

e.SortDirection = SortDirection.Ascending;

}

SetupSorting(e.SortExpression, e.SortDirection);

this.DataBind();

this._lastSortExpression = e.SortExpression;

this._lastSortDirection = e.SortDirection;

}

protected override void OnPageIndexChanging(GridViewPageEventArgs eArgs)

{

this.PageIndexChanging += new GridViewPageEventHandler(this.SelfSortingGridView_PageIndexChanging);

base.OnPageIndexChanging(eArgs);

}

private void SelfSortingGridView_PageIndexChanging(object sender, GridViewPageEventArgs eArgs)

{

this.PageIndex = eArgs.NewPageIndex;

if (!string.IsNullOrEmpty(this._lastSortExpression))

SetupSorting(this._lastSortExpression, this._lastSortDirection);

this.DataBind();

}

private void SetupSorting(string sortExpression, SortDirection sortDirection)

{

IEnumerable _data = null;

// This will allow LINQ to SQL to pass the sorting on to the SQL Server itself.

if (this.DataSource is IQueryable)

{

_data = (IQueryable)this.DataSource;

}

else

{

DataSourceView dataView = this.GetData();

if (dataView == null)

{

// No data to sort.

return;

}

dataView.Select(this.SelectArguments, delegate(IEnumerable data)

{

_data = data;

});

if (_data == null)

{

// No data to sort.

return;

}

}

Type dataSourceType = _data.GetType();

Type dataItemType = typeof(object);

if (dataSourceType.HasElementType)

{

dataItemType = dataSourceType.GetElementType();

}

else if (dataSourceType.IsGenericType)

{

dataItemType = dataSourceType.GetGenericArguments()[0];

}

else if (_data is IEnumerable)

{

IEnumerator dataEnumerator = _data.GetEnumerator();

if (dataEnumerator.MoveNext() && dataEnumerator.Current != null)

{

dataItemType = dataEnumerator.Current.GetType();

}

}

var fieldType = dataItemType.GetProperty(sortExpression);

object sorterObject = null;

Type sorterType = null;

// We'll handle things like LINQ to SQL differently by passing the love

// on to the provider.

PropertyInfo property = dataItemType.GetProperty(sortExpression);

if (property != null)

{

sorterType = typeof(GenericSorter<,>).MakeGenericType(dataItemType, property.PropertyType);

sorterObject = Activator.CreateInstance(sorterType);

}

else

{

sorterType = typeof(LateBoundSorter);

sorterObject = Activator.CreateInstance(sorterType);

}

this.DataSource = sorterType.GetMethod("Sort", new Type[] { dataSourceType, typeof(string), typeof(SortDirection) })

.Invoke(sorterObject, new object[] { _data, sortExpression, sortDirection });

}

protected override object SaveControlState()

{

return new object[] { this._lastSortExpression, this._lastSortDirection, base.SaveControlState() };

}

protected override void LoadControlState(object savedState)

{

object[] stateItems = savedState as object[];

if (stateItems != null && stateItems.Length == 3)

{

this._lastSortExpression = (String) stateItems[0];

this._lastSortDirection = (SortDirection) stateItems[1];

base.LoadControlState(stateItems[2]);

}

else

{

base.LoadControlState(savedState);

}

}

}

public class GenericSorter<T, PT>

{

public IEnumerable<T> Sort(IEnumerable source, string sortExpression, SortDirection sortDirection)

{

var param = Expression.Parameter(typeof(T), "item");

var sortLambda = Expression.Lambda<Func<T, PT>>(Expression.Convert(Expression.Property(param, sortExpression), typeof(PT)), param);

if (sortDirection == SortDirection.Ascending)

{

return source.OfType<T>().AsQueryable<T>().OrderBy<T, PT>(sortLambda);

}

else

{

return source.OfType<T>().AsQueryable<T>().OrderByDescending<T, PT>(sortLambda);

}

}

public IEnumerable<T> Sort(IEnumerable<T> source, string sortExpression, SortDirection sortDirection)

{

var param = Expression.Parameter(typeof(T), "item");

var sortLambda = Expression.Lambda<Func<T, PT>>(Expression.Convert(Expression.Property(param, sortExpression), typeof(PT)), param);

if (sortDirection == SortDirection.Ascending)

{

return source.AsQueryable<T>().OrderBy<T, PT>(sortLambda);

}

else

{

return source.AsQueryable<T>().OrderByDescending<T, PT>(sortLambda);

}

}

}

public class LateBoundSorter

{

public IEnumerable Sort(IEnumerable source, string sortExpression, SortDirection sortDirection)

{

if (sortDirection == SortDirection.Ascending)

{

return source.OfType<object>().OrderBy(item =>

this.GetPropertyValue(item, sortExpression));

}

else

{

return source.OfType<object>().OrderByDescending(item =>

this.GetPropertyValue(item, sortExpression));

}

}

private object GetPropertyValue(object item, string propertyName)

{

return item.GetType().GetProperty(propertyName).GetValue(item, null);

}

}

}

  • Apr 29 2009 - 10:08:36 AM brintf

    I'm trying to bind this to a generic List<T>, but I get the error message "the data source does not support server-side paging." Any idea how to make it work?

  • May 15 2009 - 12:58:31 AM sycho

    I have the same problem but there seems to be no answer! Did you solved the problem?

You must be logged in to add comments. If you have not already done so, you can create an account here. If you already are a member, you first need to login before you can comment.

SingingEels.com as of Mar 15 2010 - 03:20:09 PM - (0.046878)