Error after applying multi-property sort

Error after applying multi-property sort

Old forum URL: forums.lhotka.net/forums/t/11635.aspx


JasonG posted on Tuesday, October 09, 2012

Hello, I wonder if this error (bottom of post) i'm getting is "normal". First I'll give you some background info.


I'm using CSLA 4.3.

I have a Windows UI with a Datagridview that is databound to a SortedBindingList property. Because of a business rule the list is a DynamicBindingListBase<Child>.

I'm using the SortedBindingList so that the user can also sort by clicking the column headers.

Everythings works until after I apply the sort. After considerable searching the only way I found to do a multi-propery search is using Dynamic Linq.

But the problem if I sort using Dynamic Linq I get this error. Should I be expecting this? or is there something I'm doing wrong?

This is how I implement the sort..

bindingSource.DataSource = New SortedBindingList<child>(data.AsQueryable().OrderBy("").ToList());

I know there has been numberous post regarding sorting and Dynamic Linq, and I've read them all hoping to find an answer or something that would lead me in the right direction but I found nothing that helped.

This is the error that I get.

 

JonnyBee replied on Tuesday, October 09, 2012

You can use linq for all the filtering and sorting - however you must add the code to sort and wont get it automatically.

You can also use MultiColumn sorting in SortedBindingList by implementing you own PropertyDescriptor class that will return a GetValue combined of several fields.

JasonG replied on Tuesday, October 09, 2012

thanks for your reply.

The sort actually works using linq, but I eventually get this error.

Could you give me a simple example of how i could implement a PropertyDescriptor class?

thanks.

 

JonnyBee replied on Tuesday, October 09, 2012

I had a chat with the developer that actually did this and he chose to implement this a "virtual" MultiSortProperty that can be defined in the list and implement IComparable so that he can compare each individual property of the correct type. That is also under the assumption that it a type of "pre-defined" sortorder that the list should/could have knowledge of and maybe even specify sortorder per field.

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace MyBusiness.Logic
{
    public class MultiSortProperty : IComparable
    {
        #region Private properties
 
        private readonly List<IComparable> _properties;
        private readonly List<ListSortDirection> _directions;

        #endregion

        #region Public properties

        public int PropertyCount
        {
            get { return _properties.Count; }
        }

        #endregion

        #region Constructors
        public MultiSortProperty()
        {
            _properties = new List<IComparable>();
            _directions = new List<ListSortDirection>();
        }

        public MultiSortProperty(IComparable one, IComparable two) : this()
        {
            AddProperty(one, ListSortDirection.Ascending);
            AddProperty(two, ListSortDirection.Ascending);
        }

        public MultiSortProperty(IComparable one, IComparable two, ListSortDirection directionOne, ListSortDirection directionTwo)  : this()
        {
            AddProperty(one, directionOne);
            AddProperty(two, directionTwo);
        }

        public MultiSortProperty(IComparable one, IComparable two, IComparable three)  : this()
        {
            AddProperty(one, ListSortDirection.Ascending);
            AddProperty(two, ListSortDirection.Ascending);
            AddProperty(three, ListSortDirection.Ascending);
        }
 
        public MultiSortProperty(IComparable one, IComparable two, IComparable three, IComparable four): this()
        {
            AddProperty(one, ListSortDirection.Ascending);
            AddProperty(two, ListSortDirection.Ascending);
            AddProperty(three, ListSortDirection.Ascending);
            AddProperty(four, ListSortDirection.Ascending);
        }
 
        public MultiSortProperty(IComparable one, IComparable two, IComparable three, ListSortDirection directionOne, ListSortDirection directionTwo, ListSortDirection directionThree) : this()
        {
            AddProperty(one, directionOne);
            AddProperty(two, directionTwo);
            AddProperty(three, directionThree);
        }
 
        public MultiSortProperty(IComparable one, IComparable two, IComparable three,IComparable four, ListSortDirection directionOne,
            ListSortDirection directionTwo, ListSortDirection directionThree , ListSortDirection directionFour) : this()
        {
            AddProperty(one, directionOne);
            AddProperty(two, directionTwo);
            AddProperty(three, directionThree);
            AddProperty(four, directionFour);
        }
        #endregion
 
        #region Business methods
        public void AddProperty(IComparable element, ListSortDirection direction)
        {
            _properties.Add(element);
            _directions.Add(direction);
        }
 
        public IComparable GetProperty(int index)
        {
            return _properties[index];
        }
 
        public IComparable GetListSortDirection(int index)
        {
            return _directions[index];
        }
 
        private int CompareToRecursive(MultiSortProperty that, int i)
        {
            // Make sure we have identical objects
            if (that == null || that._properties.Count != _properties.Count) return -1;
            var res = _propertiesIdea.CompareTo(that._propertiesIdea);
            if (res == 0)
            {
                // They equal, check next property in list
                if (_properties.Count > i + 1) return CompareToRecursive(that, i + 1);
                return 0; // All elements equal
            }
            // They don't equal - return 1 or -1 depending on ListSortDirection
            if (_directionsIdea == ListSortDirection.Descending) res = 0 - res;
            return res;
        }
        #endregion 
 
        #region IComparable Members
 
        public int CompareTo(object obj)
        {
            if (_directions.Count == 0) return 0;
            var that = obj as MultiSortProperty;
            if (that == null) return -1;
            return CompareToRecursive(that, 0);
        }
        #endregion
    }
}

Usage in a list:
  public MultiSortProperty MyMultiSortProperty
  {
   get { return new MultiSortProperty(Property1, Property2, Property3); }
  }
 
And then apply sort on the list field
  <sortedBindingList>.ApplySort(MyMultiSortProperty);

JasonG replied on Tuesday, October 09, 2012

this is good, thanks.

but i have a couple futher questions due to my lack of programming knowledge.

What do you mean by "usage in a list"? you mean add this property to the child class or the DynamicBindingListBase class or something else? Also, the SortBindingList I'm using doesn't accept "MyMultiSortProperty" has a parameter.

thanks.

 

JonnyBee replied on Tuesday, October 09, 2012

You add the MultiSortProperty to the item in the list.

The use the MultiSortProperty.Name as input to the ApplySort method.

dg78 replied on Wednesday, February 20, 2013

Hello Jonny,

I try to convert your code in VB and I have a problem with the lines :

           var res = _propertiesIdea.CompareTo(that._propertiesIdea);

...
            if (_directionsIdea == ListSortDirection.Descending) res = 0 - res;

what is the bright idea  Idea  ?

Thanks in advance for help

Dominique

dg78 replied on Wednesday, February 20, 2013

I found the answer :   i replace the idea by  (i),  IE change (i) by the symbol 'idea'

and it is OK

  Private Function CompareToRecursive(ByVal that As MultiSortProperty, ByVal i As Integer) As Integer

    ' Make sure we have identical objects

    If that Is Nothing OrElse that._properties.Count <> _properties.Count Then

      Return -1

    End If

    Dim res As Integer = _properties(i).CompareTo(that._properties(i))

    If res = 0 Then

      ' They equal, check next property in list

      If _properties.Count > i + 1 Then

        Return CompareToRecursive(that, i + 1)

      End If

      ' All elements equal

      Return 0

    End If

    ' They don't equal - return 1 or -1 depending on ListSortDirection

    If _directions(i) = ListSortDirection.Descending Then

      res = 0 - res

    End If

    Return res

  End Function

Wonderful code

Thanks Jonny

Copyright (c) Marimer LLC