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
}
Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
IComparer compares two objects that it's given. IComparable is implemented by the object that is being compared, for the purpose of comparing with another one of itself. It is a good idea to implement IComparable for sorting objects.
C# IComparable interfaceThe IComparable interface defines a generalized type-specific comparison method that a value type or class implements to order or sort its instances. The IComparable is implemented by types whose values can be ordered or sorted. The interface requires the CompareTo method to be implemented.
All numeric types (such as Int32 and Double) implement IComparable, as do String, Char, and DateTime.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With