简体   繁体   中英

Int32? with IComparable

I have a DataGridView whose datasource is a BindingList. MyObj has a few nullable properties (like int? and DateTime?) I want to implement sorting to my binding list, so the DataGridView can sort the column when the user clicks on the column header.

After some digging around, I found and followed the answer of this question ( DataGridView Column sorting with Business Objects ).

I can't get that solution to work for Nullable types because they don't implement IComparable. Even for classes that implement IComparable like String, ApplySortCore(...) fails when the String has a null value.

Is there a solution for this? Or do I have to implement a wrapper class for "Int32?" ?

eg

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
}

Nullable<int> may not implement IComparable , but surely int does. And Nullable<T> always boxes to T (for instance when you cast to an interface, such as IComparable , which is a boxing conversion). So comparing/sorting on nullable properties should not be a problem.

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

So, the check in the sample at the top does not work right. Try this:

Type interfaceType = prop.PropertyType.GetInterface("IComparable");
// Interface not found on the property's 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

One more addition: if you want null values to work as well (both string and nullable types), you could try this re-implementation of 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));
}

There's no need to look for IComparable directly, just let the sorting methods themselves sort it out.

When comparing your nullable types can you do something like this...

Int32? val1 = 30;
Int32 val2 = 50;

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM