Итак, WPF не поддерживает стандартное поведение сортировки или фильтрации для представлений CompositeCollections, так какова же будет лучшая практика для решения этой проблемы.
Имеются две или более коллекции объектов разных типов. Вы хотите объединить их в одну коллекцию с возможностью сортировки и фильтрации (без необходимости вручную реализовывать сортировку или фильтр).
Один из подходов, который я рассматривал, заключается в создании новой коллекции объектов с несколькими основными свойствами, включая те, по которым я хотел бы сортировать коллекцию, и экземпляром объекта каждого типа.
class MyCompositeObject
{
enum ObjectType;
DateTime CreatedDate;
string SomeAttribute;
myObjectType1 Obj1;
myObjectType2 Obj2;
{
class MyCompositeObjects : List<MyCompositeObject> { }
А затем в цикле пройтись по двум коллекциям объектов, чтобы создать новую составную коллекцию. Очевидно, что это немного грубый метод, но он будет работать. Я получу все стандартные возможности сортировки и фильтрации в новой коллекции составных объектов, а также смогу наложить на нее шаблон данных для правильного отображения элементов списка в зависимости от того, какой тип хранится в этом составном элементе.
Какие есть предложения, как сделать это более элегантным способом?
Упомянутый вами метод "грубой силы" на самом деле является идеальным решением. При этом все объекты находятся в оперативной памяти, нет узких мест ввода-вывода, поэтому на любом современном компьютере можно отсортировать и отфильтровать миллионы объектов менее чем за секунду.
Наиболее элегантным способом работы с коллекциями является пространство имен System.Linq в .NET 3.5
Спасибо - я тоже рассматривал вариант LINQ to объектам, но меня беспокоит потеря гибкости для типизированных данных шаблонов, которые мне нужны для отображения объекты в моем списке.
Если вы не можете в данный момент предсказать, как люди будут сортировать и фильтровать вашу коллекцию объектов, то вам стоит обратить внимание на пространство имен System.Linq.Expressions для построения лямбда-выражений по запросу во время выполнения (сначала вы позволяете пользователю построить выражение, затем компилируете, выполняете и в конце используете пространство имен reflection для перечисления результатов). Это более сложная для понимания, но бесценная возможность, возможно (для меня однозначно) даже более новаторская, чем сам 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);
}
Обновление: я нашел гораздо более элегантное решение:
class MyCompositeObject
{
DateTime CreatedDate;
string SomeAttribute;
Object Obj1;
{
class MyCompositeObjects : List<MyCompositeObject> { }
Я обнаружил, что благодаря отражению, конкретный тип, хранящийся в Obj1, разрешается во время выполнения и применяется шаблон DataTemplate, соответствующий типу, как и ожидалось!