Подтвердить что ты не робот

Используйте собственный IComparer <T> с Linq OrderBy

У меня есть общий

List<MyClass>

где MyClass имеет свойство InvoiceNumber, которое содержит такие значения, как:

200906/1
200906/2
..
200906/10
200906/11
200906/12

Мой список привязан к

BindingList<T>

который поддерживает сортировку с помощью linq:

protected override void ApplySortCore(
           PropertyDescriptor property, ListSortDirection direction)
{

    _sortProperty = property;
    _sortDirection = direction;

    var items = this.Items;

    switch (direction)
    {
        case ListSortDirection.Ascending:
            items = items.OrderByDescending(x => property.GetValue(x)).ToList();
            break;
        case ListSortDirection.Descending:
            items = items.OrderByDescending(x => property.GetValue(x)).ToList();
            break;
    }

    this.Items = items;

}

Однако сопоставление по умолчанию сортирует (как предполагается) следующим образом:

200906/1
200906/10
200906/11
200906/12
200906/2

что в этом случае неприятно.

Теперь я хочу использовать свой IComparer<T> с этим. Это выглядит так:

public class MyComparer : IComparer<Object>
{

    public int Compare(Object stringA, Object stringB)
    {
        String[] valueA = stringA.ToString().Split('/');
        String[] valueB = stringB.ToString().Split('/');

        if(valueA .Length != 2 || valueB .Length != 2)
             return String.Compare(stringA.ToString(), stringB.ToString());

        if (valueA[0] == valueB[0]) 
        {
          return String.Compare(valueA[1], valueB[1]);
        }
        else
        {
          return String.Compare(valueA[0], valueB[0]);
        }

    }

}

и изменил код ApplySortCore, чтобы использовать этот IComparer:

case ListSortDirection.Ascending:
    MyComparer comparer = new MyComparer();
    items = items.OrderByDescending(
              x => property.GetValue(x), comparer).ToList();
    break;

Когда я отлаживаю свой код, я вижу, что MyComparer.Compare(object, object) вызывается несколько раз и возвращает правильные значения (-1, 0, 1) для метода сравнения.

Но мой список по-прежнему сортируется как "неправильный" способ. Я что-то упускаю? Я понятия не имею.

4b9b3361

Ответ 1

Ваш компартер выглядит неправильно. Вы по-прежнему просто сортируете текстовое упорядочение по умолчанию. Конечно, вы хотите разбора двух чисел и сортировки на основе этого:

public int Compare(Object stringA, Object stringB)
{
    string[] valueA = stringA.ToString().Split('/');
    string[] valueB = stringB.ToString().Split('/');

    if (valueA.Length != 2 || valueB.Length != 2)
    {
        stringA.ToString().CompareTo(stringB.ToString()));
    }

    // Note: do error checking and consider i18n issues too :)
    if (valueA[0] == valueB[0]) 
    {
        return int.Parse(valueA[1]).CompareTo(int.Parse(valueB[1]));
    }
    else
    {
        return int.Parse(valueA[0]).CompareTo(int.Parse(valueB[0]));
    }
}

(Обратите внимание, что это не соответствует вашему вопросу о том, что вы отлаживали и проверяли, что Compare возвращает правильное значение, но я боюсь, что я подозреваю человеческую ошибку на этом фронте.)

Кроме того, Sven right - изменение значения items не изменяет ваш список привязок вообще. Вы должны добавить:

this.Items = items;

внизу вашего метода.

Ответ 4

Не можем ли мы сделать так:

public class MyComparer : IComparer<string>
{

    public int Compare(string stringA, string stringB)
    {
        string small = stringA;
        string big = stringB;
        if (stringA.Length > stringB.Length)
        {
            small = stringB;
            big = stringA;
        }
        else if (stringA.Length < stringB.Length)
        {
            small = stringA;
            big = stringB;
        }
        for (int j = 0; j < small.Length; j++)
        {
            if (Convert.ToInt32(small[j]) > Convert.ToInt32(big[j])) return -1;
            if (Convert.ToInt32(small[j]) < Convert.ToInt32(big[j])) return 1;
        }

        //big is indeed bigger
        if (big.Length > small.Length) return 1;

        //finally they are smae
        return 0;
    }
}

Использование:

string[] inputStrings = {"_abc*&","#almnp","abc" };
//string[] inputStrings = { "#", "_", "_a", "@", "_" };
MyComparer computer = new MyComparer();
var kola = inputStrings.OrderBy(x => x, new MyComparer()).ToArray();

Это то же самое, что:

    Array.Sort(inputStrings, StringComparer.Ordinal);

Ответ 5

Сортированный список привязан только к элементам локальной переменной, а не к свойству Items вашего списка привязки, поэтому он остается несортированным.

[Изменить] В принципе, вы просто отбрасываете результат ваших усилий по сортировке; -)