C# Можно ли абстрагировать предложение LINQ orderby в параметр функции?

У меня есть ObservableCollection, привязанный к представлению списка WPF. Я хочу иметь возможность сортировать столбцы элемента управления ListView, щелкнув заголовок столбца. Для этого я сортирую ObservableCollection и позволяю привязке позаботиться об обновлении графического интерфейса.

Для сортировки ObservableCollection я использую следующий код:

sortedData = new ObservableCollection<Tag>( from x in data
                                            orderby x.ID descending
                                            select x );
data = sortedData;

NB: данные привязаны к ListView

Проблема, с которой я сталкиваюсь, заключается в том, что для каждого из столбцов будет много кода копирования и вставки для достижения желаемого эффекта. Можно ли передать часть инструкции LINQ "orderby x.ID по убыванию" в качестве параметра функции?

Или есть более простой способ добиться желаемого результата?


person TK.    schedule 06.06.2011    source источник


Ответы (6)


Вы можете использовать Func как параметр метода, содержащий лямбда-выражение.

Если вы хотите упорядочить каждый отдельный тип по его идентификатору, вы также можете указать интерфейс для всех этих типов и использовать общий метод.

Например

public ObservableCollection<Tag> Sort(Func<ObservableCollection<Tag>> sortFunc)  
{  
    //do something else  
    data = sortFunc();  
    //do something else  
}

который можно назвать как

Sort(list.OrderByDescending(x => x.ID));

в каком списке находится ваша ObservableCollection.

person thekip    schedule 06.06.2011
comment
Это хороший ответ, но определенно требует примера кода. - person Merlyn Morgan-Graham; 06.06.2011

Вы определяете функцию сортировки следующим образом:

Func<Tag, int> sortFunc = x => -x.ID;

(Сортировка по отрицательному идентификатору имеет тот же эффект, что и сортировка по убыванию идентификатора.)

Затем вы можете применить эту функцию сортировки к любому IEnumerable<Tag>:

var sortedData = new ObservableCollection<Tag>(data.OrderBy(sortFunc));
person Heinzi    schedule 06.06.2011
comment
Ах, этот int в Func‹› сбил меня с толку... Я пытался поместить туда тип коллекции, такой как Func‹INode, List‹INode›› (что на самом деле не имеет никакого смысла). Таким образом, первый аргумент — это тип класса в коллекции, второй — возвращаемый тип свойства в этом классе (это делает гораздо больше смысла) Спасибо за совет по отрицательному результату, чтобы эмулировать убывание - person Josh Stribling; 20.12.2011

Мне удалось добиться этого благодаря идее kip передать Func в функцию, например.

sortColumn( "ID", x => x.ID );

protected void sortColumn<T>( string name, Func<Tag, T> selector )
{
    ObservableCollection<Tag> sortedData = new ObservableCollection<Tag>( TagData.OrderBy( selector ) );

    data = sortedData;
}
person TK.    schedule 06.06.2011

Я думаю, вы ищете Dynamic Linq.

Посмотрите, поможет ли этот образец: -

http://msdn.microsoft.com/en-gb/bb737920.aspx

http://msdn.microsoft.com/en-gb/bb737920.aspx

person Deepesh    schedule 06.06.2011

Вы можете использовать Dynamic Linq для этого

с ним вы можете написать что-то вроде:

var sortExpr = "x.ID";

IQueryable<Tag> sortedQuery = query.OrderBy(sortExpr);

person Vladimir    schedule 06.06.2011

Вы можете использовать динамический запрос. Он будет составлять операторы LINQ на лету, динамически, во время выполнения.

Например:

var query =
           db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
           OrderBy("CompanyName").
           Select("New(CompanyName as Name, Phone)");

Вы можете получить его здесь: http://code.msdn.microsoft.com/DynamicQuery-f65f6a4d

person pixparker    schedule 17.03.2014