c# - BindingList<T>.Sort() 表现得像 List<T>.Sort()

标签 c# .net winforms sorting bindinglist

我正在尝试编写可用于我的应用程序的 SortableBindingList。我发现很多关于如何实现基本排序支持的讨论,以便 BindingList 在 DataGridView 或其他一些绑定(bind)控件的上下文中使用时进行排序,包括来自 StackOverflow 的这篇帖子:
DataGridView sort and e.g. BindingList<T> in .NET

这一切都非常有帮助,我已经实现了代码、进行了测试等,一切正常,但在我的特殊情况下,我需要能够支持对 Sort() 的简单调用,并让该调用使用默认 IComparable.CompareTo() 进行排序,而不是调用 ApplySortCore(PropertyDescriptor, ListSortDirection)。

原因是因为我有相当多的代码依赖于 Sort() 调用,因为这个特定的类最初是从 List 继承的,最近更改为 BindingList。

具体来说,我有一个名为 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?
    }
}

我曾多次尝试在 Sort() 中重新调整 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();
     }

  }

最佳答案

仅仅为了排序而模拟一个属性可能有点矫枉过正。 首先要看的是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();
    }    
}

关于c# - BindingList<T>.Sort() 表现得像 List<T>.Sort(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1063917/

相关文章:

c# - 设置文本框线程问题

c# - 将 DataGridView 绑定(bind)到对象列表

c# - 在 MVC4 Twitter Bootstrap C# 中设置文本框格式

c# - 有没有办法在不转换字符串的情况下在 C# 中比较日期 "strings"?

.NET : Get property name in attribute

.net - 如何在可移植类库中使用 MEF?

c# - 在显示我的 C# Windows 窗体时关闭 'Show window contents while dragging' 设置

c# - 在 XElement.Load 上保留\r\n

c# - ASP.NET Core 中的 HttpRequestMessage 是什么?

.net - 使用.Net Core创建UDP套接字