2009-06-30 45 views
20

私のアプリケーションに使用できるSortableBindingListを書き込もうとしています。
DataGridView sort and e.g. BindingList<T> in .NETBindingList <T>リストのように動作する.Sort()<T> .Sort()

これはすべての非常に有用である:私はDataGridViewのかStackOverflowのからこの記事を含むいくつかの他のバインドされたコントロールのコンテキストで使用する場合するBindingListがソートされますように、基本的なソートのサポートを実装する方法についての議論の多くを発見しました私はコードを実装し、テストしたなど、それはすべて動作しますが、私の特定の状況では、私はSort()への単純な呼び出しをサポートし、その呼び出しにデフォルトのIComparable.CompareTo()を使用する必要がありますApplySortCore(PropertyDescriptor、ListSortDirection)を呼び出すのではなく、並べ替えを行います。

なぜなら、この特定のクラスはもともとListから継承され、最近BindingListに変更されたため、Sort()呼び出しに依存するかなりのコードがあるからです。

具体的には、私はVariableCodeというクラスとVariableCodeListというコレクションクラスを持っています。 VariableCodeはIComparableをを実装し、そこでのロジックがなどいくつかのプロパティに基づいて、適度に複雑です...

public class VariableCode : ... IComparable ... 
{ 
    public int CompareTo(object p_Target) 
    { 
     int output = 0; 
     //some interesting stuff here 
     return output; 
    } 
} 

public class VariableCodeList : SortableBindingList<VariableCode> 
{ 
    public void Sort() 
    { 
     //This is where I need help 
     // How do I sort this list using the IComparable 
     // logic from the class above? 
    } 
} 

I)は、(いくつかの並べ替えにApplySortCore方法を再利用する試みが失敗した作りましたが、何を阻止し続けます私は、ApplySortCoreがPropertyDescriptorのソートを期待しているため、IComparable.CompareTo()ロジックを使用する方法を理解できません。

誰かが正しい方向に向かうことができますか?

多くのありがとうございます。


編集:これはMarcのレスポンスに基づいて作成されたもので、今後の参考になるものです。

/// <summary> 
    /// Sorts using the default IComparer of T 
    /// </summary> 
    public void Sort() 
    { 
    sort(null, null); 
    } 
    public void Sort(IComparer<T> p_Comparer) 
    { 
    sort(p_Comparer, null); 
    } 
    public void Sort(Comparison<T> p_Comparison) 
    { 
    sort(null, p_Comparison); 
    } 
    private void sort(IComparer<T> p_Comparer, Comparison<T> p_Comparison) 
    { 

    m_SortProperty = null; 
    m_SortDirection = ListSortDirection.Ascending; 

    //Extract items and sort separately 
    List<T> sortList = new List<T>(); 
    this.ForEach(item => sortList.Add(item));//Extension method for this call 
    if (p_Comparison == null) 
    { 
     sortList.Sort(p_Comparer); 
    }//if 
    else 
    { 
     sortList.Sort(p_Comparison); 
    }//else 

    //Disable notifications, rebuild, and re-enable notifications 
    bool oldRaise = RaiseListChangedEvents; 
    RaiseListChangedEvents = false; 
    try 
    { 
     ClearItems(); 
     sortList.ForEach(item => this.Add(item)); 
    } 
    finally 
    { 
     RaiseListChangedEvents = oldRaise; 
     ResetBindings(); 
    } 

    } 

答えて

16

ちょうどその並べ替えを行うプロパティをエミュレートすることはおそらく過剰です。 最初に調べるのはComparer<T>.Defaultです。それは、しかし、最も簡単な方法があることが判明するかもしれません:

  • は、データをリロード

    • List<T>または類似
    • ソート抽出したデータにデータを抽出
    • 無効通知
    • 「リセット」メッセージを送信する

    btwでは、既存の並べ替えの際に通知を無効にする必要があります。

    public void Sort() { 
        // TODO: clear your "sort" variables (prop/order) 
    
        T[] arr = new T[Count]; 
        CopyTo(arr, 0); 
        Array.Sort(arr); 
        bool oldRaise = RaiseListChangedEvents; 
        RaiseListChangedEvents = false; // <=== oops, added! 
        try { 
         ClearItems(); 
         foreach (T item in arr) { 
          Add(item); 
         } 
        } finally { 
         RaiseListChangedEvents = oldRaise; 
         ResetBindings(); 
        }  
    } 
    
  • +2

    Nice、Marc。ありがとうございました。私は何かが欠けていると思っていたし、簡単な解決策を実行するだけではなく、どこかにサポートが組み込まれていると思っていました。通知の良い点も同様です。 List クラスをサポートするように、フレキシブルなデリゲートベースの並べ替えをサポートできるように、配列ではなくリストを使って巻きました。投稿は最終コードで更新されます。 –

    9

    私は同じ問題を抱えていましたが、この記事は私がそれを解決するのを助けました!

    私は、私はあなたとそれを共有したい、拡張機能として(マルクさんとポールのコードに基づいて)このソリューションを実装し、2つの単純なソート方法を追加したよう:

    public static void SortAscending<T, P>(this BindingList<T> bindingList, Func<T, P> sortProperty) 
        { 
         bindingList.Sort(null, (a, b) => ((IComparable<P>)sortProperty(a)).CompareTo(sortProperty(b))); 
        } 
        public static void SortDescending<T, P>(this BindingList<T> bindingList, Func<T, P> sortProperty) 
        { 
         bindingList.Sort(null, (a, b) => ((IComparable<P>)sortProperty(b)).CompareTo(sortProperty(a))); 
        } 
        public static void Sort<T>(this BindingList<T> bindingList) 
        { 
         bindingList.Sort(null, null); 
        } 
        public static void Sort<T>(this BindingList<T> bindingList, IComparer<T> comparer) 
        { 
         bindingList.Sort(comparer, null); 
        } 
        public static void Sort<T>(this BindingList<T> bindingList, Comparison<T> comparison) 
        { 
         bindingList.Sort(null, comparison); 
        } 
        private static void Sort<T>(this BindingList<T> bindingList, IComparer<T> p_Comparer, Comparison<T> p_Comparison) 
        { 
    
         //Extract items and sort separately 
         List<T> sortList = new List<T>(); 
         bindingList.ForEach(item => sortList.Add(item));//Extension method for this call 
         if (p_Comparison == null) 
         { 
          sortList.Sort(p_Comparer); 
         }//if 
         else 
         { 
          sortList.Sort(p_Comparison); 
         }//else 
    
         //Disable notifications, rebuild, and re-enable notifications 
         bool oldRaise = bindingList.RaiseListChangedEvents; 
         bindingList.RaiseListChangedEvents = false; 
         try 
         { 
         bindingList.Clear(); 
         sortList.ForEach(item => bindingList.Add(item)); 
         } 
         finally 
         { 
         bindingList.RaiseListChangedEvents = oldRaise; 
         bindingList.ResetBindings(); 
         } 
    
        } 
    
        public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) 
        { 
         if (source == null) throw new ArgumentNullException("source"); 
         if (action == null) throw new ArgumentNullException("action"); 
    
         foreach (T item in source) 
         { 
          action(item); 
         } 
        } 
    

    が、これは便利です願っています。

    +1

    非常にいい、きれいで使いやすい。個人的には、私はBindingListを拡張メソッドから返すことを好みました。 – PhilHoy