Динамическая сортировка ObservableCollection <object>, когда столбец является строкой - PullRequest
3 голосов
/ 20 ноября 2019

У меня есть Observable Collection из примерно 5000 объектов, возвращаемых из запроса SQL в мою службу WCF. Меня попросили отсортировать коллекцию по 3 полям в объекте. Для краткости предположим, что это моя модель c #:

public class TestObject{
     public string type1{get; set;}
     public string type2{get; set;}
     public string type3(get; set;}
}

А вот некоторые тестовые данные, которые я должен попытаться отсортировать:

   public ObservableCollection<TestObject> TestObjects = new ObservableCollection<TestObject>();
   TestObjects.Add(new TestObject('708','4','(A)'));
   TestObjects.Add(new TestObject('7','41B','1(A)'));
   TestObjects.Add(new TestObject('69','2','45'));
   TestObjects.Add(new TestObject('708','4','(B)'));
   TestObjects.Add(new TestObject('69','2','5'));
   TestObjects.Add(new TestObject('7','41','1(B)'));
   TestObjects.Add(new TestObject('7','41',''));

Есть ли способ динамической сортировкиэто так, что коллекция Observable возвращается отсортированной, как это?

  {(7,41,''),(7,41,1(B)),(7,41B,1(A)),(69,2,5),(69,2,45),(708,4,(A)),(708,4,(B))}

До сих пор я был в состоянии отсортировать их по type1, но затем пытался отсортировать винтами type2 порядок вверх от сортировки type1. Вот метод, который я использовал, чтобы попытаться отсортировать, после чего я назвал его:

   protected virtual ObservableCollection<TestObject> SortTestObjects(ObservableCollection<TestObjects> unsortedObjects, string level){
        var SortedObjects = new ObservableCollection<TestObject>();
        Comparison<TestObject> numericComp;
        Comparison<TestObject> comparison;
        Comparison<TestObject> AlphaNumericComp;
        bool sortNumeric = false;
        switch (level)
        {
            case "type1":
                numericComp = (a, b) =>
                {
                    var aKey = Convert.ToDouble(a.type1);
                    var bKey = Convert.ToDouble(b.type1);
                    return aKey.CompareTo(bKey);
                };
                AlphaNumericComp = (a, b) =>
                {
                    return string.CompareOrdinal(a.type1, b.type1);
                };
                sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type1.IsNumeric());

                break;
            case "type2":
                 numericComp = (a, b) =>
                {
                    var aKey = Convert.ToDouble(a.type2);
                    var bKey = Convert.ToDouble(b.type2);
                    return aKey.CompareTo(bKey);
                };
                 AlphaNumericComp = (a, b) =>
                {
                    return string.CompareOrdinal(a.type2, b.type2);
                };
                sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type2.IsNumeric());

                break;
            case "type3":
                 numericComp = (a, b) =>
                {
                    var aKey = Convert.ToDouble(a.type3);
                    var bKey = Convert.ToDouble(b.type3);
                    return aKey.CompareTo(bKey);
                };
                 AlphaNumericComp = (a, b) =>
                {
                    return string.CompareOrdinal(a.type3, b.type3);
                };
                sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type3.IsNumeric());

                break;
            default:
                numericComp = (a, b) =>
                {
                    var aKey = Convert.ToDouble(a.type1);
                    var bKey = Convert.ToDouble(b.type1);
                    return aKey.CompareTo(bKey);
                };
                AlphaNumericComp = (a, b) =>
                {
                    return string.CompareOrdinal(a.type1, b.type1);
                };
                sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type1.IsNumeric());

                break;
        }
        comparison = sortNumeric ? numericComp : AlphaNumericComp;
        unsortedObjects.ToList().Sort(comparison);
        foreach(var obj in unsortedOjects){
          SortedObjects.Add(obj)
         }
        return SortedObjects;
     }

    Public ObservableCollection<TestObject> SortAllTestObjects(){
         var sort1 = SortTestObjects(TestObjects, "type1");
         var sort2 = SortTestObjects(sort1, "type2");
         var sort3 = SortTestObjects(sort2, "type3");
         return sort3;
    }

** Правка: вот запрос SQL, который я бы использовал в этом примере. Я полностью справляюсь с изменением запроса до тех пор, пока я получаю правильный заказ в клиенте **

Select type1, type2, type3 from dbo.testObject tO where tO.del_date is null

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация. Любая помощь или конструктивная обратная связь будут отличными!

Ответы [ 2 ]

1 голос
/ 25 ноября 2019

Итак, вот что я в итоге сделал, чтобы решить проблему. В объекте я объединил типы

public class TestObject{
 public string type1{get; set;}
 public string type2{get; set;}
 public string type3{get; set;}
 public string types{get;set;}
}

и в методе, в котором заполняются объекты TestObjects, я добавил это в:

public ObservableCollection<TestObject> TestObjects = new ObservableCollection<TestObject>();
 TestObjects.Add(new TestObject('708','4','(A)','708.4.(A)'));
 TestObjects.Add(new TestObject('7','41B','1(A)','7.41B.1(A)'));
 TestObjects.Add(new TestObject('69','2','45', '69.2.45'));
 TestObjects.Add(new TestObject('708','4','(B)', '708.4.(B)'));
 TestObjects.Add(new TestObject('69','2','5', '69.2.5'));
 TestObjects.Add(new TestObject('7','41','1(B)', '7.41.1(B)'));
 TestObjects.Add(new TestObject('7','41','', '7.41.'));
  TestObjects= SortObjects(TestObjects);

Далее я создал собственный метод сравненияв ViewModel, используя «Shlwapi.dll»:

   [DllImport("Shlwapi.dll", Charset = Charset.Unicode)]
   private static extern int StrCmpLogicalW(string x, string y); 

   public ObservableCollection<TestObject> SortObjects(ObservableCollection<TestObject> unsortedObjects){
   var sortedCollection = new ObservableCollection<TestObject>();
   var objectList = new List<TestObject>();
   foreach(var obj in unsortedObjects){
      objectList.Add(obj);
     }
   Comparison<TestObject> typesComp = (a,b) =>{
      var aKey = a.types;
      var bKey = b.types;
      return StrCmpLogicalW(aKey,bKey);
   }
   objectList.Sort(typesComp);
   foreach(var obj in objectList){
     sortedCollection.Add(obj);
   }
   return sortedCollection;
   }

Этот метод позволяет мне возвращать коллекцию TestObjects в порядке возрастания. Все еще работает с переключателем в порядке убывания и обновлю его, когда я его получу.

ОБНОВЛЕНИЕ: Вот метод SortObjects со способностью обращения

   public ObservableCollection<TestObject> SortObjects(ObservableCollection<TestObject> unsortedObjects, bool IsAscend){
      var sortedCollection = new ObservableCollection<TestObject>();
      var objectList = new List<TestObject>();
      foreach(var obj in unsortedObjects){
         objectList.Add(obj);
      }
      Comparison<TestObject> typesComp = (a,b) =>{
         var aKey = a.types;
         var bKey = b.types;
         return StrCmpLogicalW(aKey,bKey);
      }
      objectList.Sort(typesComp);
      if(!isAscend){
         objectsList.Reverse();
      }
      foreach(var obj in objectList){
        sortedCollection.Add(obj);
      }
      return sortedCollection;
    } 

И затем он вызывается, передавая параметр true / false, как это для возрастания:

 TestObjects = SortObjects(TestObjects, true);

и так в порядке убывания:

 TestObjects = SortObjects(TestObjects, false);
0 голосов
/ 20 ноября 2019

Вы можете использовать OrderBy () и ThenBy ().

Пример

public class SomeClass
{
    public string PropA { get; }
    public string PropB { get; }
}

protected ObservableCollection<SomeClass> SomeFunc(ObservableCollection<SomeClass> collection)
{

    var sorted=collection.OrderBy(s => s.PropA).ThenBy(s => s.PropB);
    ObservableCollection<SomeClass> sortedObservable=new ObservableCollection<SomeClass>();
    foreach(var item in sorted)
    {
        sortedObservable.Add(item);
    }
    return sortedObservable;
}

Для учета числовых значений в вашей строке вы можете использовать пользовательский компаратор, Ответ на этот пример является хорошим

Ссылка на заметки Microsoft

...