ObjectListView: пользовательский сортировщик

В элементе управления ObjectListView(http://objectlistview.sourceforge.net/html/cookbook.htm), я пытаюсь добавить собственный сортировщик, игнорирующий префиксы «The» и «A».

Мне удалось сделать это с помощью обычного ListView, но теперь, когда я переключился на ObjectListView (намного больше возможностей и простоты), я не могу сделать то же самое.

Ниже приведен основной компаратор в коде ObjectListView, я думаю...

public int Compare(object x, object y)
    {
        return this.Compare((OLVListItem)x, (OLVListItem)y);
    }

Например, исходный сортировщик по возрастанию (игнорируя «A» и «The»)

public class CustomSortAsc : IComparer
        {
            int IComparer.Compare(Object x, Object y)
            {
                string[] px = Convert.ToString(x).Split(' ');
                string[] py = Convert.ToString(y).Split(' ');
                string newX = "";
                string newY = "";

                for (int i = 0; i < px.Length; i++)
                {
                    px[i] = px[i].Replace("{", "");
                    px[i] = px[i].Replace("}", "");
                }
                for (int i = 0; i < py.Length; i++)
                {
                    py[i] = py[i].Replace("{", "");
                    py[i] = py[i].Replace("}", "");
                }

                if ((px[1].ToLower() == "a") || (px[1].ToLower() == "the"))
                {
                    if (px.Length > 1)
                    {
                        for (int i = 2; i < px.Length; i++)
                            newX += px[i];
                    }
                }
                else
                {
                    for (int i = 1; i < px.Length; i++)
                        newX += px[i];
                }

                if ((py[1].ToLower() == "a") || (py[1].ToLower() == "the"))
                {
                    if (py.Length > 1)
                    {
                        for (int i = 2; i < py.Length; i++)
                            newY += py[i];
                    }
                }
                else
                {
                    for (int i = 1; i < py.Length; i++)
                        newY += py[i];
                }


                return ((new CaseInsensitiveComparer()).Compare(newX, newY));
            }

person Mike    schedule 23.10.2009    source источник
comment
Можете ли вы добавить больше информации, например, какой результат вы получаете, как вы подключаете CustomSortAsc к представлению списка и т. д.?   -  person Ludovic Chabant    schedule 24.10.2009


Ответы (2)


Хотя это не имеет прямого отношения к вашей проблеме, могу ли я предложить некоторые улучшения кода? По-видимому, ваши исходные объекты x и y представляют собой слова, разделенные пробелами. Не уверен, что вы намеренно не соединяете их с пробелами, но я оставил это так.

public static class Extensions
{
    public static IEnumerable<T> SkipIf<T>(this IEnumerable<T> items, Predicate<T> pred)
        {
            return pred(items.First()) ? items.Skip(1) : items;
        }
}

public class CustomSortAsc : IComparer
{
    int IComparer.Compare(Object x, Object y)
    {
        var ignorePredicates = new List<string> { "a", "the" }; 
        var px = Convert
                    .ToString(x)
                    .Replace("{", "")
                    .Replace("}", "")
                    .Split(' ')
                    .SkipIf(s => ignorePredicates.Contains(s.ToLower()))
                    .ToArray();

        var py = Convert
                    .ToString(y)
                    .Replace("{", "")
                    .Replace("}", "")
                    .Split(' ')
                    .SkipIf(s => ignorePredicates.Contains(s.ToLower()))
                    .ToArray();

        var newX = string.Join("", px);
        var newY = string.Join("", py);

        return string.Compare(newX, newY, true);
    }
}

Вы можете просто использовать SkipWhile<>, но это пропустит несколько "a" и "the" в начале. Может быть, тогда вам не нужно расширение SkipIf<>.

person ChrisWue    schedule 16.03.2011

Установите делегат CustomSorter и в этом делегате поместите ListItemSorter в ObjectListView

this.incidentListView.CustomSorter = delegate(OLVColumn column, SortOrder order) {
     this.incidentListView.ListViewItemSorter = new CustomSortAsc();
};

См. этот рецепт сортировки

Лучше, чем выполнять всю эту работу при каждом сравнении, кэшировать значение сортировки для каждого из объектов вашей модели. Если значение равно "{The} целых девять ярдов", сохраните "целые девять ярдов" и выполните простое (и быстрое) сравнение строк с этими значениями.

У ObjectListView есть свой собственный форум.

person Grammarian    schedule 24.10.2009