Int32? с IComparable

У меня есть DataGridView, источником данных которого является BindingList. MyObj имеет несколько свойств с нулевым значением (например, int? И DateTime?). Я хочу реализовать сортировку в списке привязки, поэтому DataGridView может сортировать столбец, когда пользователь нажимает на заголовок столбца.

После некоторого поиска я нашел и выполнил ответ на этот вопрос (сортировка столбцов DataGridView с бизнес-объектами).

Я не могу получить это решение для работы с типами Nullable, потому что они не реализуют IComparable. Даже для классов, которые реализуют IComparable как String, ApplySortCore (...) терпит неудачу, когда String имеет нулевое значение.

Есть ли решение для этого? Или мне нужно реализовать класс-оболочку для "Int32?"?

например,

public class Int32Comparable : IComparable
{
    public int? Value { get; set; }

    #region IComparable<int?> Members

    public int CompareTo(object other)
    {
        // TODO: Implement logic here
        return -1;
    }

    #endregion
}

Ответ 1

Nullable<int> может не реализовывать IComparable, но, безусловно, int делает. И Nullable<T> всегда привязывается к T (например, при нажатии на интерфейс, например IComparable, который является преобразованием бокса). Поэтому сравнение/сортировка по свойствам с нулевым значением не должно быть проблемой.

int? value = 1;
IComparable comparable = value; // works; even implicitly

Итак, проверка в примере сверху не работает правильно. Попробуйте следующее:

Type interfaceType = prop.PropertyType.GetInterface("IComparable");
// Interface not found on the property type. Maybe the property was nullable?
// For that to happen, it must be value type.
if (interfaceType == null && prop.PropertyType.IsValueType)
{
    Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
    // Nullable.GetUnderlyingType only returns a non-null value if the
    // supplied type was indeed a nullable type.
    if (underlyingType != null)
        interfaceType = underlyingType.GetInterface("IComparable");
}
if (interfaceType != null)
   // rest of sample

Еще одно дополнение: если вы хотите, чтобы нулевые значения также работали (как с строковыми, так и с нулевыми типами), вы можете попробовать эту повторную реализацию SortCore(...):

protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
    IEnumerable<MyClass> query = base.Items;
    if (direction == ListSortDirection.Ascending)
        query = query.OrderBy( i => prop.GetValue(i) );
    else
        query = query.OrderByDescending( i => prop.GetValue(i) );
    int newIndex = 0;
    foreach (MyClass item in query)
    {
        this.Items[newIndex] = item;
        newIndex++;
    }
    this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}

Нет необходимости искать IComparable напрямую, просто разрешите сами сортировать методы.

Ответ 2

При сравнении типов с нулевым значением вы можете сделать что-то вроде этого...

Int32? val1 = 30;
Int32 val2 = 50;

Int32 result = (val1 as IComparable).CompareTo(val2);