• Blog
  • Info Support
  • Career
  • Training
  • International Group
  • Info Support
  • Blog
  • Career
  • Training
  • International Group
  • Search
logo InfoSupport
  • Latest blogs
  • Popular blogs
  • Experts
      • All
      • Bloggers
      • Speakers
  • Meet us
  • About us
    • nl
    • en
    • .NET
    • 3D printing
    • Advanced Analytics
    • Agile
    • Akka
    • Alexa
    • Algorithms
    • Api's
    • Architectuur
    • Artificial Intelligence
    • ATDD
    • Augmented Reality
    • AWS
    • Azure
    • Big Data
    • Blockchain
    • Business Intelligence
    • Chatbots
    • Cloud
    • Code Combat
    • Cognitive Services
    • Communicatie
    • Containers
    • Continuous Delivery
    • CQRS
    • Cyber Security
    • Dapr
    • Data
    • Data & Analystics
    • Data Science
    • Data Warehousing
    • Databricks
    • DataOps
    • Developers life
    • DevOps
    • Digital Days
    • Digital Twin
    • Docker
    • eHealth
    • Enterprise Architecture
    • Event Sourcing
    • Hacking
    • Infrastructure & Hosting
    • Innovatie
    • Integration
    • Internet of Things
    • Java
    • Machine Learning
    • Microservices
    • Microsoft
    • Microsoft Bot Framework
    • Microsoft Data Platform
    • Mobile Development
    • Mutation Testing
    • Open source
    • Pepper
    • Power BI
    • Privacy & Ethiek
    • Python
    • Quality Assistance & Test
    • Quality Assurance & Test
    • Requirements Management
    • Scala
    • Scratch
    • Security
    • SharePoint
    • Software Architecture
    • Software development
    • Software Factory
    • SQL Server
    • SSL
    • Start-up
    • Startup thinking
    • Stryker
    • Test Quality
    • Testing
    • TLS
    • TypeScript
    • Various
    • Web Development
    • Web-scale IT
    • Xamarin
    • All
    • Bloggers
    • Speakers
Home » How to enable sorting on a GridView using an IEnumerable list as datasource
  • How to enable sorting on a GridView using an IEnumerable list as datasource

    • By Patrick Gilhuijs
    • Various 15 years ago
    • Various 0 comments
    • Various Various
    How to enable sorting on a GridView using an IEnumerable list as datasource

    For the last months I’ve been working together with my colleague Raimond Brookman on new software for our software factory named Endeavour. The software is asp.net related. Today I ran into a problem with Microsofts GridView control. I was  using  an ObjectDataSource control that can provide a list of domain objects of type IEnumerable. This was all working fine until I wanted to enable sorting. I found out that built in  sorting capability of the GridView  control is not supported when using an object of type IEnumerable as a datasource. So I converted the IEnumerable  list to a DataTable. But this class doesn’t support Nullable types and automatically converts my enum values to integers..:( That’s not what I wanted/needed.

    Then I started thinking whether it could be possible to have this basic sorting done by using Linq! Well, it certainly is possible. Enumerable.OrderBy<> is your friend when it comes to sorting of a List of domain objects that need to be shown in a GridView. You can use Linq like this for example:

    List<Order> orders = new List<Order>();

    //<some code to fill the list… >

    orders.OrderBy<Order, string>(o => o.OrderDate);

    This code example above will sort the orders list ascending using the OrderDate property. It&rsquo;s also possible to do a multi sort (sort on two properties) using ThenBy<> after the OrderBy<> method, like this:

    List<Order> orders = new List<Order>();

    //<some code to fill the list… >

    orders.OrderBy<Order, string>(o => o.OrderDescription).ThenBy<Order, DateTime?>(o => o.OrderDate);&nbsp;&nbsp;&nbsp;&nbsp;

    There are also OrderByDescending or ThenByDescending equivalents of the methods&hellip;

    &nbsp;Now, in my piece of software that I&rsquo;m building I don&rsquo;t know upfront with what type of domain object I&rsquo;m dealing with. So I cannot use the above statements (or something like that) in my code. Runtime I&rsquo;ll have a list with domain objects,&nbsp;knowlegde of the type of the domain object and I&rsquo;ll get the sort expression passed from the GridView control. Wouldn&rsquo;t it be nice to be able to dynamically create a linq query with a lambda expression as in the above example&hellip;. It&rsquo;s nice and also possible J! Here&rsquo;s some code that will do exactly that. The method in the example below&nbsp;&nbsp;gets &nbsp;a list of objects, a sort expression (multi sort expression) &nbsp;and the type of the domain object passed as parameters. It builds the correct expression tree and executes it on the list. And voila, there&rsquo;s a list of type IOrderedEnumerable that the GridView control can use to bind against. This is the first version of the code, I didn&#39;t test it thoroughly yet&nbsp;so there migth be some bugs in there. May be it also needs some refactoring, but it is just provided as an example to show&nbsp;how one could do this.

    private IEnumerable&nbsp; SortSelectResult(IEnumerable selectResult, string sortExpression, Type searchResultType)

    &nbsp;{

    &nbsp;&nbsp;&nbsp;&nbsp; string[] expressions = sortExpression.Split(&#39;,&#39;);

    &nbsp;&nbsp;&nbsp;&nbsp; bool isFirstLamdaExpression = true;

    &nbsp;&nbsp;&nbsp;&nbsp; MethodCallExpression finalCallExpression = null;

    &nbsp;&nbsp;&nbsp;&nbsp; ///walk through the parts of the sortExpression (e.g. &quot;Description ASC, OrderDate DESC&quot;)

    &nbsp;&nbsp;&nbsp;&nbsp; foreach (string expression in expressions)

    &nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Cut the SortDirection part loose from the column name

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string[] expressionParts = expression.Split(&#39; &#39;);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Determine sort direction

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortDirection sortDirection = DetermineSortDirection(expressionParts);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Get the propertyInfo for this property

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PropertyInfo propInfo = searchResultType.GetProperty(expressionParts[_ColummNamePartIndex]);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type propertyType = propInfo.PropertyType;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Build a lambda expression like this:

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //pagedOrders.OrderBy<Order, string>(c => c.OrderDescription).ThenBy<Order, DateTime>(c => c.OrderDate);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //to enable sorting a enumerable list.

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ParameterExpression param = Expression.Parameter(searchResultType, propInfo.Name);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expression selector = Expression.Property(param, propInfo);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LambdaExpression lambdaExpression = Expression.Lambda(selector, param);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isFirstLamdaExpression)

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string methodName = &quot;OrderBy&quot;;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (sortDirection == SortDirection.Descending)

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; methodName += &quot;Descending&quot;;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MethodCallExpression orderByCall =

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expression.Call(typeof(Enumerable), methodName, new Type[] { searchResultType, propertyType },

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expression.Constant(selectResult), lambdaExpression);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finalCallExpression = orderByCall;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    &nbsp; }

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string methodName = &quot;ThenBy&quot;;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (sortDirection == SortDirection.Descending)

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodName += &quot;Descending&quot;;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MethodCallExpression thenByCall =

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MethodCallExpression.Call(finalCallExpression,&nbsp;methodName,

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Type[] { searchResultType, propertyType },

    Expression.Constant(selectResult), lambdaExpression);

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finalCallExpression = thenByCall;

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

    &nbsp;&nbsp;&nbsp; }

    &nbsp;&nbsp;&nbsp;

    &nbsp;&nbsp;&nbsp; if (finalCallExpression != null)

    &nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;selectResult = (IEnumerable)selectResult.AsQueryable().Provider.Execute(finalCallExpression);

    &nbsp;&nbsp;&nbsp; }

    &nbsp;&nbsp;&nbsp;&nbsp; return (IEnumerable)selectResult;

    }

    private SortDirection DetermineSortDirection(string[] expressionParts)

    {

    &nbsp;&nbsp;&nbsp;&nbsp; if (expressionParts.Length <= 1 ||

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string.IsNullOrEmpty(expressionParts[_SortDirectionPartIndex]) ||

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; expressionParts[_SortDirectionPartIndex].ToUpperInvariant() == &quot;ASC&quot;)

    &nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SortDirection.Ascending;

    &nbsp;&nbsp;&nbsp;&nbsp; }

    &nbsp;&nbsp;&nbsp;&nbsp; else if (expressionParts[_SortDirectionPartIndex].ToUpperInvariant() == &quot;DESC&quot;)

    &nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SortDirection.Descending;

    &nbsp;&nbsp;&nbsp;&nbsp; }

    &nbsp;&nbsp;&nbsp;&nbsp; else

    &nbsp;&nbsp;&nbsp;&nbsp; {

    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SortDirection.Ascending;

    &nbsp;&nbsp;&nbsp;&nbsp; }

    }

    &nbsp;&nbsp;The&nbsp;OrderBy(Descending) / ThenBy(Descending) &nbsp;methods have also an overload where you can provide a comparer class, so that you can do some advanced stuff when needed. May be I&#39;ll need it also but I don&#39;t now yet ; ) Also I must say that the GridView control doesn&#39;t support multi sort out of the box, but it&#39;s not that hard to implement that.

    Hope this helps!

    &nbsp;

    &nbsp;

    Share this

Patrick Gilhuijs

View profile

IT Training at Info Support

Which training fits you?

Consultancy

Consultancy

Related blogs

  • Video Conferencing en OBS Studio koppelen: online prese…

    Video Conferencing en OBS Studio koppelen: online prese… Maaike Brouwer - 2 years ago

  • Verantwoordelijkheid pakken in jouw eigen persoonlijke …

    Verantwoordelijkheid pakken in jouw eigen persoonlijke … Stephan Versteegh - 2 years ago

  • Tips voor als je gaat afstuderen

    Tips voor als je gaat afstuderen Bart Renders - 3 years ago

Data Discovery Channel

  • MLOps

  • Explainable AI - Break open the blackbox

  • Toekomstvaste microservice data architecturen

Nieuwsbrief

* verplichte velden

Contact

  • Head office NL
  • Kruisboog 42
  • 3905 TG Veenendaal
  • T +31 318 552020
  • Call
  • Mail
  • Directions
  • Head office BE
  • Generaal De Wittelaan 17
  • bus 30 2800 Mechelen
  • T +32 15 286370
  • Call
  • Mail
  • Directions

Follow us

  • Twitter
  • Facebook
  • Linkedin
  • Youtube

Newsletter

Sign in

Extra

  • Media Library
  • Disclaimer
  • Algemene voorwaarden
  • ISHBS Webmail
  • Extranet
Beheer cookie toestemming
Deze website maakt gebruik van Functionele en Analytische cookies voor website optimalisatie en statistieken.
Functioneel Always active
De technische opslag of toegang is strikt noodzakelijk voor het legitieme doel het gebruik mogelijk te maken van een specifieke dienst waarom de abonnee of gebruiker uitdrukkelijk heeft gevraagd, of met als enig doel de uitvoering van de transmissie van een communicatie over een elektronisch communicatienetwerk.
Voorkeuren
De technische opslag of toegang is noodzakelijk voor het legitieme doel voorkeuren op te slaan die niet door de abonnee of gebruiker zijn aangevraagd.
Statistieken
De technische opslag of toegang die uitsluitend voor statistische doeleinden wordt gebruikt. De technische opslag of toegang die uitsluitend wordt gebruikt voor anonieme statistische doeleinden. Zonder dagvaarding, vrijwillige naleving door uw Internet Service Provider, of aanvullende gegevens van een derde partij, kan informatie die alleen voor dit doel wordt opgeslagen of opgehaald gewoonlijk niet worden gebruikt om je te identificeren.
Marketing
De technische opslag of toegang is nodig om gebruikersprofielen op te stellen voor het verzenden van reclame, of om de gebruiker op een website of over verschillende websites te volgen voor soortgelijke marketingdoeleinden.
Manage options Manage services Manage vendors Read more about these purposes
Voorkeuren
{title} {title} {title}