2009-08-11 10 views
10

Mam DataGridView którego źródłem danych jest BindingList. MyObj ma kilka właściwości nullable (np. Int? I DateTime?) Chcę zaimplementować sortowanie do mojej listy powiązań, więc DataGridView może sortować kolumnę, gdy użytkownik kliknie nagłówek kolumny.Int32? z IComparable

Po krótkich poszukiwaniach znalazłem i podążałem za odpowiedzią na to pytanie (DataGridView Column sorting with Business Objects).

Nie mogę sprawić, aby to rozwiązanie działało z typami zerowymi, ponieważ nie implementują one IComparable. Nawet dla klas, które implementują IComparable takie jak String, ApplySortCore (...) zawodzi, gdy String ma wartość null.

Czy istnieje rozwiązanie tego problemu? Czy muszę zaimplementować klasę opakowania dla "Int32?" ?

np

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 
} 

Odpowiedz

11

Nullable<int> nie może realizować IComparable, ale na pewno int robi. I Nullable<T> zawsze skrzynki do T (na przykład podczas przesyłania do interfejsu, na przykład IComparable, co jest konwersją bokserską). Zatem porównywanie/sortowanie na właściwościach zerowalnych nie powinno stanowić problemu.

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

Tak więc, sprawdzenie próbki u góry nie działa poprawnie. Spróbuj tego:

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 bardziej Ponadto: jeśli chcesz wartości null do pracy, jak również (zarówno łańcuch i dopuszczające wartość null rodzaje), można spróbować tego ponownego wdrożenia 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)); 
} 

Nie ma'S trzeba szukać bezpośrednio, po prostu pozwól, aby metody sortowania same je rozwiązały.

+0

Wielkie dzięki. Muszę również ustawić _sortPropertyValue = prop; _sortDirectionValue = kierunek; _isSortedValue = true; , aby kod zadziałał. Wielkie dzięki :) – David

+0

Re "porównywanie/sortowanie na właściwościach zerowalnych nie powinno stanowić problemu." - chyba, że ​​właściwość ma wartość 'null', w takim przypadku otrzymasz wyjątek środowiska wykonawczego. (Przypuszczam - nie próbowałem tego.) – ToolmakerSteve

+0

@ToolmakerSteve, 'OrderBy' i' OrderByDescending' nie mają nic przeciwko, gdy właściwość zwraca 'null'. Domyślne narzędzie porównawcze, którego używa, posortuje wartości "null" na górze. Będziesz miał problem tylko wtedy, gdy sama lista zawiera wpis "null". – Ruben

3

Porównując swoje zerowalne typów można zrobić coś takiego ...

Int32? val1 = 30; 
Int32 val2 = 50; 

Int32 result = (val1 as IComparable).CompareTo(val2); 
Powiązane problemy