覆盖的 winform ListBox.Sort() 未按预期调用

Overridden winform ListBox.Sort() not getting called as expected

我正在尝试覆盖列表框中的排序方法以按降序排序。

代码:

public CustomSortListBox()
    : base()
{
}

protected override void Sort()
{
    if (this.Items.Count > 1)
    {
        bool swapped;
        do
        {
            int counter = this.Items.Count - 1;
            swapped = false;

            while (counter > 0)
            {
                // set this to != to reverse sorting
                if (this.Items[counter].ToString().CompareTo(this.Items[counter - 1].ToString()) != -1)
                {
                    object temp = Items[counter];
                    this.Items[counter] = this.Items[counter - 1];
                    this.Items[counter - 1] = temp;
                    swapped = true;
                }

                counter -= 1;
            }
        }
        while (swapped);
    }
}

现在,我直觉地期望每当将项目添加到列表中时都会调用此方法,这似乎是它在 ListBox.Sorted = true 时与基本 ListBox 一起工作的方式。但是,在将项目添加到列表后使用我的 CustomSortListBox,我的自定义排序没有得到遵守,而且,当项目列表更改时,没有调用覆盖的方法,甚至没有击中断点。

然后我读了这个 https://gfaraj.wordpress.com/2008/07/31/custom-sorting-for-listbox-in-c/,上面写着 "Don’t forget that Sort is only called when the Sorted property goes from false to true" 这对我来说似乎很可笑,但可以肯定的是,当切换排序关闭和重新打开时,我的自定义排序被调用并起作用。

有趣的是,在此之后,保留 Sorted = true,添加的新项目使用基本的 Sort() 方法进行排序,创建升序和降序项目的混合。直到您再次切换 Sorted false -> true。

我什至会接受放置 Sorted = false; 的 hacky 解决方案。排序=真;在 ItemsChanged 的​​事件处理程序中,但这样的事件不存在。

我哪里做错了,我怎样才能在添加列表时遵守此排序覆盖?

(我看到了C#'s ListBox doesn't see my overrided Sort() method,但是他的问题不明确,好像只有"gone away",而且他随机选择的答案不理想,甚至因为无法访问保护级别而无法编译)

您似乎明白要调用 Sort() 方法,ListBox.Sorted 属性 需要转换为 true。这是有记录的,虽然很差。据我所知,这是唯一一次调用 Sort() 方法,这种理解与文档一致。

Interestingly, after this, leaving Sorted = true, new items added are sorted using the base Sort() method, creating a mixture of ascending and descending items. Until you toggle Sorted false -> true again.

当您向 ListBox 添加项目时,顺序不是由 Sort() 方法处理,而是由控件的集合对象处理。该对象执行二进制搜索以找到插入新项目的正确位置。不幸的是,为此在列表框项目文本上使用字符串比较是硬编码的。

这就是添加项目导致它们根据默认实现排序的原因。但它没有使用 "the base Sort() method" 来做到这一点。

对于 Winforms ListBox class,如果你想要有效地排序项目,你最好的选择可能是不要覆盖 Sort() 也不要使用 Sorted 属性。相反,提供一个辅助方法来添加新项目,并让该方法对 Items 集合进行适当的二进制搜索以找到插入位置。

无论如何,您都必须实现一个辅助方法来获得添加项目的通知,并且进行排序插入比在每次插入时重新排序整个集合更有效。

您可以(如评论中所建议的那样)将排序的集合绑定到 ListBox,但这将需要更多的工作,特别是因为 AFAIK 没有任何支持绑定的内置集合类型并且本质上是排序的。