2009-08-11 10 views
10

Tengo un DataGridView cuyo origen de datos es un BindingList. MyObj tiene algunas propiedades que aceptan nulos (como int? Y DateTime?) Deseo implementar la ordenación en mi lista de enlaces, por lo que DataGridView puede ordenar la columna cuando el usuario hace clic en el encabezado de la columna.Int32? con IComparable

Después de buscar, encontré y seguí la respuesta a esta pregunta (DataGridView Column sorting with Business Objects).

No puedo conseguir que esa solución funcione para los tipos Nullable porque no implementan IComparable. Incluso para las clases que implementan IComparable como String, ApplySortCore (...) falla cuando la cadena tiene un valor nulo.

¿Existe una solución para esto? ¿O tengo que implementar una clase contenedora para "Int32?" ?

por ejemplo

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 
} 

Respuesta

11

Nullable<int> puede no aplicar IComparable, pero seguramente int hace. Y Nullable<T> siempre encaja en T (por ejemplo, cuando transfiere a una interfaz, como IComparable, que es una conversión de boxeo). Por lo tanto, comparar/clasificar propiedades anulables no debería ser un problema.

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

Por lo tanto, el control en la muestra en la parte superior no funciona bien. Prueba esto:

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 

Uno más además: si desea que los valores nulos para trabajar así (tanto de cadena y tipos anulables), puede probar esta re-implementación de 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)); 
} 

No hay necesita buscar directamente el IComparable, simplemente deje que los métodos de clasificación lo resuelvan.

+0

Muchas gracias. También necesito establecer _sortPropertyValue = prop; _sortDirectionValue = direction; _isSortedValue = true; para que el código funcione. Muchas gracias :) – David

+0

Re "comparar/ordenar en propiedades que aceptan nulos" no debería ser un problema. " - a menos que la propiedad tenga el valor 'null', en cuyo caso obtendrá una excepción en tiempo de ejecución. (Supongo - No lo he probado.) – ToolmakerSteve

+0

@ToolmakerSteve, 'OrderBy' y' OrderByDescending' no importa cuando la propiedad devuelve 'null'. El Comparer predeterminado que utiliza clasificará los valores 'null' en la parte superior. Solo tendrá un problema cuando la lista en sí contenga una entrada 'null'. – Ruben

3

Al comparar los tipos anulables se puede hacer algo como esto ...

Int32? val1 = 30; 
Int32 val2 = 50; 

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