2009-06-30 10 views
20

मैं एक सॉर्ट करने योग्य बाइंडिंग लिस्ट लिखने का प्रयास कर रहा हूं जिसे मैं अपने आवेदन के लिए उपयोग कर सकता हूं।
DataGridView sort and e.g. BindingList<T> in .NETबाइंडिंगलिस्ट <T> .Sort() एक सूची <T> की तरह व्यवहार करने के लिए .ॉर्ट()

यह सब बहुत उपयोगी है: मैं कैसे मूलभूत रूप से क्रमबद्ध समर्थन लागू करने के लिए इतना है कि जब एक DataGridView या StackOverflow से इस पोस्ट सहित कुछ अन्य बाध्य नियंत्रण के संदर्भ में इस्तेमाल किया BindingList सॉर्ट जाएगा के बारे में चर्चा के बहुत सारे मिल गया है और मैंने कोड, परीक्षण, इत्यादि लागू किया है और यह सब काम कर रहा है, लेकिन मेरी विशेष स्थिति में, मुझे सॉर्ट() को एक सरल कॉल का समर्थन करने में सक्षम होना चाहिए और उस कॉल को डिफ़ॉल्ट IComparable.CompareTo() करने के लिए उपयोग करना होगा SortSortCore (PropertyDescriptor, ListSortDirection) पर कॉल करने के बजाय सॉर्टिंग।

कारण यह है कि मेरे पास सॉर्ट() कॉल के आधार पर बहुत अधिक कोड है क्योंकि यह विशेष वर्ग मूल रूप से सूची से विरासत में मिला है और हाल ही में इसे बाइंडिंगलिस्ट बन गया है।

तो विशेष रूप से, मेरे पास वेरिएबलकोड नामक एक वर्ग है और वेरिएबलकोडलिस्ट नामक संग्रह श्रेणी है। 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? 
    } 
} 

मैं कुछ (क्रमबद्ध में ApplySortCore विधि को पुनः उद्देश्य) पर प्रयास विफल कर दिया है लागू करता है, लेकिन क्या रोकने रहता है मुझे यह है कि ApplySortCore एक प्रॉपर्टी डिस्क्रिप्टर को अपनी तरह से करने की अपेक्षा करता है और मैं यह नहीं समझ सकता कि इसे IComparable.CompareTo() तर्क का उपयोग करने के लिए कैसे प्राप्त किया जाए।

क्या कोई मुझे सही दिशा में इंगित कर सकता है?

बहुत धन्यवाद।


संपादित करें: यह भविष्य का संदर्भ के लिए मार्क की प्रतिक्रिया के आधार पर अंतिम कोड है।

/// <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> या इसी तरह
  • प्रकार निकाले गए डेटा में डेटा निकालने
  • सूचनाएं अक्षम
  • डेटा को फिर से लोड
  • पुन: सक्षम सूचनाएं
  • भेज एक "रीसेट" संदेश

बीटीडब्ल्यू, आपको अपने मौजूदा प्रकार के दौरान अधिसूचनाएं अक्षम करना चाहिए।

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

नाइस, मार्क। धन्यवाद। मैंने सोचा था कि मैं कुछ खो रहा था और सरल समाधान को निष्पादित करने के बजाए कहीं कुछ समर्थन में बनाया गया था। अधिसूचनाओं पर भी अच्छा बिंदु। मैं एक ऐरे की बजाय आंतरिक रूप से एक सूची का उपयोग करके घायल हो गया ताकि मैं लचीली प्रतिनिधि आधारित सॉर्टिंग का समर्थन कर सकूं (जैसे सूची वर्ग समर्थन)। पोस्ट अंतिम कोड के साथ अद्यतन किया गया है। –

9

मुझे एक ही समस्या थी और इस पोस्ट ने मुझे इसे हल करने में मदद की!

के रूप में मैं इस समाधान एक विस्तार के रूप (मार्क के और पॉल कोड के आधार पर) लागू किया और दो साधारण प्रकार के तरीकों कहा, मैं इसे आपके साथ साझा करना चाहते हैं:

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

बहुत अच्छा, साफ और उपयोग करने में आसान। व्यक्तिगत रूप से मैंने विस्तार विधि से बाइंडिंगलिस्ट को वापस करना पसंद किया। – PhilHoy

संबंधित मुद्दे