Заказ ObservableCollection с помощью Linq и IComparer
-
11-12-2019 - |
Вопрос
Я хочу упорядочить ObservableCollection в алфавитном порядке, потому что мне не нужно создавать еще одну привязку.Я видел, что мы могли бы использовать Linq и метод OrderBy.Я также хотел бы использовать личный IComparer, потому что мне придется организовывать сложные данные (списки в другие списки), но VS говорит мне, что я не могу использовать свой собственный компаратор:
(дайте ссылку на ошибку, потому что мой VS на французском языке)
http://msdn.microsoft.com/en-gb/library/hxfhx4sy%28v=vs.90%29.aspx
Есть идеи ?
private void SortGraphicObjectsAscending(object sender, RoutedEventArgs e)
{
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
}
И мой собственный компаратор (который уже опробован)
public class GraphicObjectComparer : IComparer<GraphicObject>
{
int order = 1;
public GraphicObjectComparer(Boolean ascending)
{
if (!ascending)
{
order = -1;
}
}
public GraphicObjectComparer()
{
}
public int Compare(GraphicObject x, GraphicObject y)
{
return String.Compare(x.Nom, y.Nom, false) * order;
}
}
Спасибо за ваши ответы.В любом случае у меня есть другая проблема.Как сказал Майкл, я использую более сложный компаратор, но для другой сущности.Этот объект отображается в виде иерархического дерева, и объект может содержать список других объектов того же типа.
Я не смог протестировать свой GraphicObject, поскольку у меня нет доступа к БД (в данный момент объекта не было).Судя по тестам моего VideoEntity, кажется, что моя ObservableCollection не отсортирована так, как я хочу (я создаю еще одну).Я хочу перевернуть его в алфавитном порядке, но это не работает.
public class VideoEntityComparer : IComparer<VideoEntity>
{
int order = 1;
public VideoEntityComparer(Boolean ascending)
{
if (!ascending)
{
this.order = -1; // so descending
}
}
public VideoEntityComparer()
{
}
public int Compare(VideoEntity x, VideoEntity y)
{
if ((x is BaseDirectory && y is BaseDirectory) || (x is BaseSite && y is BaseSite) || (x is VideoEncoder && y is VideoEncoder))
{
return string.Compare(x.Nom, y.Nom, false) * order; // only objects of the same type are sorted alphabetically
}
else if ((x is BaseDirectory && y is BaseSite) || (x is BaseSite && y is VideoEncoder))
{
return -1;
}else
{
return 1;
}
}
}
private void SortDirectoriesDescending(object sender, RoutedEventArgs e)
{
ObservableCollection<BaseDirectory> tempDir = new ObservableCollection<BaseDirectory>(
Directories.OrderBy(directory => directory, new VideoEntityComparer(false)));
Directories = tempDir;
}
PS:кстати, я действую на DependancyProperty.Это правильный способ сделать это?(Я новичок в WPF)
Решение
Проблема с этой строкой заключается в определении OrderBy
что вы пытаетесь использовать:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer
)
В этом методе есть два разных общих параметра: TSource
и TKey
. TSource
очевидно, это то же самое, что TSource
для источника IEnumerable
.А TKey
Параметр — это тот, который компилятор пытается вывести, но безуспешно, потому что вы пытаетесь использовать два разных типа.Ваш звонок:
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
Ваш первый параметр - это Func<GraphicObject, string>
но ваш второй параметр - это IComparer<GraphicObject>
;это означает, что вы используете TKey = string
в одном месте и TKey = GraphicObject
в другом.
Первый параметр, Func<>
делегат — «ключевой селектор»;это то, как ты говоришь OrderBy
по каким значениям сортировать.Поскольку ваш IComparer<>
сортирует по весь GraphicObject
пример, это то, что вы должны выбрать в качестве ключа:
GraphicObjects.OrderBy(go => go, new GraphicObjectComparer(true));
Я предполагаю, что ваш собственный объект сравнения на самом деле более сложен, чем тот, который вы показали, потому что ваш образец сравнения довольно избыточен:
var asc = GraphicObjects.OrderBy(go => go.Nom);
var desc = GraphicObjects.OrderByDescending(go => go.Nom);
Также обратите внимание, что ваш пример кода на самом деле ничего не делает с вновь отсортированным списком, поэтому он просто выбрасывается.LINQ-операции никогда измените перечисляемый источник, вместо этого они всегда возвращают новую, преобразованную копию.
Другие советы
твой comparer
сравнивает GraphicObject
.Так что ваши OrderBy
должно быть
GraphicObjects.OrderBy(graphicObject => graphicObject,
new GraphicObjectComparer(true));
или просто используйте
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom);
КСТАТИ, OrderBy
не сортирует на месте, вам следует назначить возвращаемое IEnumerable<GraphicsObject>
в переменную
Проблема в том, что ваш компаратор использует GraphicObject, но вы сравниваете строки.
Если вам действительно нужен ваш собственный заказ, вы можете использовать этот компаратор:
public class GraphicObjectComparer : IComparer<string>
{
int order = 1;
public GraphicObjectComparer(Boolean ascending)
{
if (!ascending)
{
order = -1;
}
}
public GraphicObjectComparer()
{
}
public int Compare(string x, string y)
{
return String.Compare(x, y, false) * order;
}
}
.
Или вы предоставляете графику для вашего компаратора, а не строки.
Для того, чтобы отсортировать обшивку для наблюдения, отражает все изменения в коллекции источника, вы можете использовать My My Обсудообменные компьютеры библиотекаОтказИспользуя эту библиотеку, которую вы можете код, как это:
var sortedGraphicObjects = GraphicObjects.Ordering(
graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
.
СортировкаGraphicobjects - это наблюдательное оборудование и отражает все изменения в сборе графиков и свойства NOM.Убедитесь, что NOM имущество уведомляет об изменениях через InotifyPropertyChanged интерфейс.