2009-08-11 4 views
10

J'ai un DataGridView dont la source de données est une BindingList. MyObj a quelques propriétés nullable (comme int? Et DateTime?) Je veux implémenter le tri à ma liste de liaison, ainsi le DataGridView peut trier la colonne quand l'utilisateur clique sur l'en-tête de colonne. Après quelques recherches, j'ai trouvé et suivi la réponse à cette question (DataGridView Column sorting with Business Objects).Int32? avec IComparable

Je ne peux pas obtenir cette solution à travailler pour les types Nullable car ils n'implémentent pas IComparable. Même pour les classes qui implémentent IComparable like String, ApplySortCore (...) échoue lorsque la chaîne a une valeur nulle.

Existe-t-il une solution pour cela? Ou dois-je implémenter une classe wrapper pour "Int32?" ?

par exemple

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 
} 

Répondre

11

Nullable<int> ne peut mettre en œuvre IComparable, mais sûrement int fait. Et Nullable<T> toujours des boîtes à T (par exemple lorsque vous lancez vers une interface, comme IComparable, qui est une conversion de boxe). Donc comparer/trier sur des propriétés nullables ne devrait pas être un problème. Par conséquent, la vérification dans l'échantillon en haut ne fonctionne pas correctement. Essayez ceci:

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 

Encore plus: si vous voulez des valeurs NULL fonctionne aussi bien (les deux cordes et types nullables), vous pouvez essayer cette réimplantation 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)); 
} 

Il n'y a pas besoin de chercher IComparable directement, laissez simplement les méthodes de tri eux-mêmes le trier.

+0

Merci beaucoup. J'ai également besoin de définir _sortPropertyValue = prop; _sortDirectionValue = direction; _isSortedValue = true; pour que le code fonctionne. Merci beaucoup :) – David

+0

Re "comparaison/tri sur les propriétés NULL ne devrait pas être un problème." - sauf si la propriété a la valeur "null", auquel cas vous obtiendrez une exception d'exécution. (Je suppose - je ne l'ai pas essayé.) – ToolmakerSteve

+0

@ToolmakerSteve, 'OrderBy' et' OrderByDescending' ne dérange pas lorsque la propriété retourne 'null'. Le Comparer par défaut utilisé va trier les valeurs null sur le dessus. Vous aurez seulement un problème quand la liste elle-même contient une entrée 'null'. – Ruben

3

Lorsque l'on compare vos types nullables pouvez-vous faire quelque chose comme ça ...

Int32? val1 = 30; 
Int32 val2 = 50; 

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