BindingList .Sort () para comportarse como una lista .Sort ()

Estoy intentando escribir una SortableBindingList que puedo usar para mi aplicación. He encontrado mucha discusión acerca de cómo implementar un soporte de clasificación básico para que BindingList se clasifique cuando se usa en el contexto de un DataGridView o algún otro control vinculado que incluye esta publicación de StackOverflow:
Ordenamiento DataGridView y, por ejemplo, BindingList en .NET

Todo esto es muy útil y he implementado el código, probado, etc. y todo funciona, pero en mi situación particular, necesito poder admitir una llamada simple a Sort () y hacer que esa llamada use el IComparable predeterminado. CompareTo () para hacer la clasificación, en lugar de hacer una llamada a ApplySortCore (PropertyDescriptor, ListSortDirection).

La razón es porque tengo una gran cantidad de código que depende de la llamada Sort () porque esta clase en particular se heredó originalmente de la Lista y se cambió recientemente para que fuera una lista de Binding.

Así que específicamente, tengo una clase llamada VariableCode y una clase de colección llamada VariableCodeList. VariableCode implementa IComparable y la lógica allí es moderadamente compleja en función de varias propiedades, etc.

public class VariableCode : ... IComparable ... { public int CompareTo(object p_Target) { int output = 0; //some interesting stuff here return output; } } public class VariableCodeList : SortableBindingList { public void Sort() { //This is where I need help // How do I sort this list using the IComparable // logic from the class above? } } 

Hice algunos bashs fallidos de reutilizar el método ApplySortCore en Sort (), pero lo que me sigue frustrando es que ApplySortCore espera que un PropertyDescriptor haga su ordenamiento y no puedo encontrar la forma de utilizar el IComparable .CompareTo () lógica.

¿Alguien me puede apuntar en la dirección correcta?

Muchas gracias.


EDITAR: Este es el código final basado en la respuesta de Marc para referencia futura.

  ///  /// Sorts using the default IComparer of T ///  public void Sort() { sort(null, null); } public void Sort(IComparer p_Comparer) { sort(p_Comparer, null); } public void Sort(Comparison p_Comparison) { sort(null, p_Comparison); } private void sort(IComparer p_Comparer, Comparison p_Comparison) { m_SortProperty = null; m_SortDirection = ListSortDirection.Ascending; //Extract items and sort separately List sortList = new List(); 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(); } } 

Emular una propiedad solo para hacer el ordenamiento es probablemente una exageración. Lo primero que hay que mirar es Comparer.Default . Sin embargo, podría resultar que lo más fácil es:

  • extraer los datos en la List o similar
  • ordenar los datos extraídos
  • Desactivar notificaciones
  • recargar los datos
  • volver a habilitar las notificaciones
  • enviar un mensaje de “reinicio”

Por cierto, también debe desactivar las notificaciones durante su clasificación existente.

 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(); } } 

Tuve el mismo problema y este post me ayudó a resolverlo.

Como implementé esta solución (basada en el código de Marc y Paul) como una extensión y agregué dos métodos de clasificación simples, me gustaría compartirla con ustedes:

 public static void SortAscending(this BindingList bindingList, Func sortProperty) { bindingList.Sort(null, (a, b) => ((IComparable

)sortProperty(a)).CompareTo(sortProperty(b))); } public static void SortDescending(this BindingList bindingList, Func sortProperty) { bindingList.Sort(null, (a, b) => ((IComparable

)sortProperty(b)).CompareTo(sortProperty(a))); } public static void Sort(this BindingList bindingList) { bindingList.Sort(null, null); } public static void Sort(this BindingList bindingList, IComparer comparer) { bindingList.Sort(comparer, null); } public static void Sort(this BindingList bindingList, Comparison comparison) { bindingList.Sort(null, comparison); } private static void Sort(this BindingList bindingList, IComparer p_Comparer, Comparison p_Comparison) { //Extract items and sort separately List sortList = new List(); 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(this IEnumerable source, Action action) { if (source == null) throw new ArgumentNullException("source"); if (action == null) throw new ArgumentNullException("action"); foreach (T item in source) { action(item); } }

Espero que esto sea de ayuda.