Сортировка составной коллекции

Таким образом, WPF не поддерживает стандартную сортировку или фильтрацию для представлений CompositeCollections, так что это лучший способ решения этой проблемы.

Существует две или более коллекций объектов разных типов. Вы хотите объединить их в единую сортируемую и фильтруемую коллекцию (без необходимости вручную реализовывать сортировку или фильтрацию).

Один из рассмотренных мною подходов - создать новую коллекцию объектов только с несколькими основными свойствами, включая те, по которым я бы хотел отсортировать коллекцию, и экземпляр объекта каждого типа.

class MyCompositeObject
{
    enum           ObjectType;
    DateTime       CreatedDate;
    string         SomeAttribute;
    myObjectType1  Obj1;
    myObjectType2  Obj2;
{
class MyCompositeObjects : List<MyCompositeObject> { }

А затем прокрутите две мои коллекции объектов, чтобы создать новую составную коллекцию. Очевидно, что это метод грубой силы, но он сработает. Я бы получил все действия сортировки и фильтрации представлений по умолчанию для моей новой коллекции составных объектов, и я мог бы поместить в нее шаблон данных для правильного отображения элементов списка в зависимости от того, какой тип фактически хранится в этом составном элементе.

Какие есть предложения, чтобы сделать это более элегантным способом?

Ответов (3)

Решение

Обновление: я нашел гораздо более элегантное решение:

class MyCompositeObject
{
    DateTime    CreatedDate;
    string      SomeAttribute;
    Object      Obj1;
{
class MyCompositeObjects : List<MyCompositeObject> { }

Я обнаружил, что из-за отражения конкретный тип, хранящийся в Obj1, разрешается во время выполнения, и тип DataTemplate применяется, как ожидалось!

Упомянутый вами метод "грубой силы" на самом деле является идеальным решением. Имейте в виду, что все объекты находятся в ОЗУ, здесь нет узких мест ввода-вывода, поэтому вы можете в значительной степени отсортировать и отфильтровать миллионы объектов менее чем за секунду на любом современном компьютере.

Самый элегантный способ работы с коллекциями - это пространство имен System.Linq в .NET 3.5.

Спасибо - я также рассмотрел LINQ to objects, но меня беспокоит потеря гибкости для шаблонов типизированных данных, которые мне нужны для отображения объектов в моем списке.

Если в данный момент вы не можете предсказать, как люди будут сортировать и фильтровать вашу коллекцию объектов, вам следует взглянуть на пространство имен System.Linq.Expressions, чтобы создавать свои лямбда-выражения по запросу во время выполнения (сначала вы позволяете пользователю создавать выражение, затем компилируете , запустите и в конце вы используете пространство имен отражения для перечисления результатов). Сложнее осмыслить это, но бесценная функция, возможно (для меня окончательно) даже более революционная, чем сам LINQ.

Я еще не очень хорошо знаком с WPF, но вижу в этом вопрос о сортировке и фильтрации List<T> коллекций.

(без необходимости вручную выполнять сортировку или фильтрацию)

Не могли бы вы пересмотреть реализацию собственных функций сортировки или фильтрации? По моему опыту, им легко пользоваться. В приведенных ниже примерах используется анонимный делегат, но вы можете легко определить свой собственный метод или класс для реализации сложной сортировки или фильтра. Такой класс может даже иметь свойства для динамической настройки и изменения сортировки и фильтрации.

Используйте List<T>.Sort(Comparison<T> comparison) с вашей пользовательской функцией сравнения:

// Sort according to the value of SomeAttribute
List<MyCompositeObject> myList = ...;
myList.Sort(delegate(MyCompositeObject a, MyCompositeObject b) 
{
    // return -1 if a < b
    // return 0 if a == b
    // return 1 if a > b
    return a.SomeAttribute.CompareTo(b.SomeAttribute);
};

Аналогичный подход для получения подгруппы элементов из списка.

Используйте List<T>.FindAll(Predicate<T> match) с вашей настраиваемой функцией фильтра:

// Select all objects where myObjectType1 and myObjectType2 are not null
myList.FindAll(delegate(MyCompositeObject a)
{
    // return true to include 'a' in the sub-collection
    return (a.myObjectType1 != null) && (a.myObjectType2 != null);
}