3

I'm trying to sort several columns of a table depending of the previous sorted column. It works fine for the first two columns. But as soon as I sort the third column the second one loses its sort. As far as I know for now there must be a problem with my foreach loop. Here is my code for sorting:

public List<object> inhaltSortieren(List<object> zuSortierendeListe, Dictionary<string, SortierRichtung> sortierung)
{
    IOrderedEnumerable<object> sortierteListe = null;
    if (sortierung.First().Value == SortierRichtung.asc)
        sortierteListe = zuSortierendeListe.OrderBy(x => x.GetType().GetProperty(sortierung.First().Key).GetValue(x, null));
    else if (sortierung.First().Value == SortierRichtung.desc)
        sortierteListe = zuSortierendeListe.OrderByDescending(x => x.GetType().GetProperty(sortierung.First().Key).GetValue(x, null));
    bool first = true;
    foreach (KeyValuePair<string, SortierRichtung> spalte in sortierung)
    {
        if (first)
        {
            first = false;
            continue;
        }
        if (spalte.Value == SortierRichtung.asc)
            sortierteListe = sortierteListe.ThenBy(x => x.GetType().GetProperty(spalte.Key).GetValue(x, null));
        else if (spalte.Value == SortierRichtung.desc)
            sortierteListe = sortierteListe.ThenByDescending(x => x.GetType().GetProperty(spalte.Key).GetValue(x, null));
    }

    return sortierteListe.ToList();
 }

Any ideas?

Update: Maybe I add some further information:

  • @param zusortierendeListe: this is the List I want to sort, it is a List of Objects
  • @param sortierung: This is the direction I want to sort, ascending or descending

The objects themselves are Lists of Tabledata

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Daniel
  • 31
  • 5

2 Answers2

3

You're passing in a Dictionary; the order in which you get values out of a Dictionary when you use it as an IEnumerable<KeyValuePair> (as your foreach loop does) is (probably) not the order in which you added them!

You'll need to use a List<KeyValuePair> (or some other ordered IEnumerable<KeyValuePair>) instead of the Dictionary, or even create a custom class to hold the field and direction and pass a List of that.

Rawling
  • 49,248
  • 7
  • 89
  • 127
1

Also have a look here

Just to make your code a bit more clear. You can put everything into the for-each loop or leave it as it is, but then use sortierung.Skip(1) in your code, because you used the first entry already. I also changed the Dictionary argument to IEnumerable> according to the previous comment.

    object GetValue(object value, string name)
    {
        return value.GetType().GetProperty(name).GetValue(value, null);
    }

    public List<object> SortContent(List<object> listToSort, Tuple<string, SortDirection>[] sortInfos)
    {
        if (sortInfos == null || sortInfos.Length == 0)
             return listToSort;

        IOrderedEnumerable<object> sortedList = null;

        foreach (var column in sortInfos)
        {
            Func<object, object> sort = x => GetValue(x, column.Key);

            bool desc = column.Value == SortDirection.Descending;

            if (sortedList == null)
                sortedList = desc ? listToSort.OrderByDescending(sort) : listToSort.OrderBy(sort);
            else
                sortedList = desc ? sortedList.ThenByDescending(sort) : sortedList.ThenBy(sort);
        }

        return sortedList.ToList();
    }
Community
  • 1
  • 1
Matthias
  • 5,574
  • 8
  • 61
  • 121
  • This will still be broken if he passes in a `Dictionary` for the `IEnumerable` parameter. (Otherwise some good ideas :) ) – Rawling Nov 23 '12 at 11:38