0

SQL Server SDK にあるように、DataGridViewコンポーネントに が設定されています。このクラスは、XML シリアル化のルート ノードとしても使用されます。SortableBindingListMicrosoft.SqlServer.Management.Controls

リストのメンバーは、2 つのプリミティブ フィールドと 1 つのオブジェクト フィールドを持つ型です。プリミティブ値を含む列は、期待どおりにソートされます。ただし、オブジェクト フィールドを含む列を並べ替えると、次の例外がスローされます。

System.InvalidOperationException was unhandled
  Message=Failed to compare two elements in the array.
  Source=mscorlib
  StackTrace:
       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
       at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
       at System.Collections.Generic.List`1.Sort(Comparison`1 comparison)
       at Microsoft.SqlServer.Management.Controls.SortableBindingList`1.ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
       at System.ComponentModel.BindingList`1.System.ComponentModel.IBindingList.ApplySort(PropertyDescriptor prop, ListSortDirection direction)
       at System.Windows.Forms.BindingSource.ApplySort(PropertyDescriptor property, ListSortDirection sort)
       ...
  InnerException: System.ArgumentException
       Message=At least one object must implement IComparable.
       Source=mscorlib
       StackTrace:
            at System.Collections.Comparer.Compare(Object a, Object b)
            at Microsoft.SqlServer.Management.Controls.SortableBindingList`1.<>c__DisplayClass1.<GetComparisionDelegate>b__0(T t1, T t2)
            at System.Array.FunctorComparer`1.Compare(T x, T y)
            at System.Collections.Generic.ArraySortHelper`1.SwapIfGreaterWithItems(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
            at System.Collections.Generic.ArraySortHelper`1.QuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer)
            at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)

スタック トレースから、比較対象のオブジェクトが比較されていないことは明らかIComparableです。または、少なくともそうあるべきです。問題のクラスは次のとおりです。

using System;
using System.Xml.Serialization;

namespace myapp.xmlobjects {
    [XmlType("error_after")]
    public class ErrorAfterObject : IComparable<ErrorAfterObject> {

        [XmlAttribute("hours")]
        public int Hours { get; set; }

        [XmlAttribute("minutes")]
        public int Minutes { get; set; }

        public ErrorAfterObject() { }

        public ErrorAfterObject(int hours, int minutes) {
            this.Hours = hours;
            this.Minutes = minutes;
        }

        public override string ToString() {
            return string.Format("{0} hr {1} min", this.Hours, this.Minutes);
        }

        public int CompareTo(ErrorAfterObject other) {
            return (this.Hours*60 + this.Minutes).CompareTo(other.Hours*60 + other.Minutes);
        }
    }
}

サニティ チェックとして、データ バインディングの後に次のデバッグ コードを追加しました。

Console.WriteLine(myGridView.Rows[0].Cells[2].ValueType.ToString());

myapp.xmlobjects.ErrorAfterObject期待どおりに戻ってきます。

問題の解決に役立つ可能性のある 3 つの質問: 私のオブジェクトは比較できないものとして型付けされていますか? どのオブジェクト タイプが比較されているかを正確に確認することは可能ですか? IComparable実装で何かを見逃したことがありますか?

前もって感謝します。

4

1 に答える 1

2

結局のところ、IComparableIComparable<T>は同じものではありません。クラス定義を次のものに置き換えます。

public class ErrorAfterObject : IComparable

および CompareTo メソッドは次のとおりです。

public int CompareTo(object other) {
    if(this.GetType() != other.GetType()) {
        return Comparer.Default.Compare(this, other);
    }
    return (this.Hours*60 + this.Minutes).CompareTo(
        ((ErrorAfterObject)other).Hours*60 + ((ErrorAfterObject)other).Minutes);
}

期待どおりに動作します。

于 2013-09-26T05:50:37.260 に答える