C# 未按预期调用重写的winform ListBox.Sort()

C# 未按预期调用重写的winform ListBox.Sort(),c#,winforms,sorting,listbox,C#,Winforms,Sorting,Listbox,我试图覆盖列表框中的sort方法以按降序排序 代码: 现在,我直觉地认为,只要将项添加到列表中,就会调用此方法,并且当ListBox.Sorted=true时,它似乎就是这样处理基本ListBox的。但是,在将项目添加到列表后使用my CustomSortListBox时,我的自定义排序没有得到遵守,而且,当项目列表更改时,重写的方法没有被调用,甚至没有命中断点 然后我读了这篇文章,它说“别忘了,只有当排序属性从false变为true时,才会调用Sort”。这对我来说似乎很神奇,但可以肯定的是,

我试图覆盖列表框中的sort方法以按降序排序

代码:

现在,我直觉地认为,只要将项添加到列表中,就会调用此方法,并且当ListBox.Sorted=true时,它似乎就是这样处理基本ListBox的。但是,在将项目添加到列表后使用my CustomSortListBox时,我的自定义排序没有得到遵守,而且,当项目列表更改时,重写的方法没有被调用,甚至没有命中断点

然后我读了这篇文章,它说“别忘了,只有当排序属性从false变为true时,才会调用Sort”。这对我来说似乎很神奇,但可以肯定的是,当切换Sorted off和back on时,我的自定义排序会被调用并起作用

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

我甚至会接受将排序=假的老套解决方案;排序=真;在ItemsChanged的事件处理程序中,但这样的事件不存在

我做错了什么?当列表添加到时,我如何使此排序覆盖得到尊重


(我看到了,但他的问题还不清楚,似乎已经“消失”了,他随机选择的答案并不理想,甚至由于无法访问保护级别而无法编译)

您似乎明白,要调用
Sort()
方法,
列表框。Sorted
属性需要转换为
true
。这是记录在案的,尽管很差。据我所知,这是唯一一次调用
Sort()
方法,这种理解与文档是一致的

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

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

这就是为什么添加项会使它们按照默认实现排序。但它并没有使用“base
Sort()
方法”来完成

对于Winforms
ListBox
类,如果希望有效地排序项目,最好不要覆盖
Sort()
或使用
sorted
属性。相反,提供一个助手方法来添加新项目,并让该方法在
项目
集合上执行适当的二进制搜索以查找插入位置

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


您可以(如注释中所建议的)将已排序的集合绑定到
列表框中,但这将需要更多的工作,特别是因为AFAIK没有任何内置的集合类型支持绑定并且固有地进行排序。

不必从MSDN文章中复制粘贴代码。您只需指出,您希望在每次添加items时调用一些自定义的
Sort
方法,以符合@SergeyBerezovskiy!关于这个“复制粘贴”问题,我也打算这么说(回复:)。另外,问题海报到底在问什么?澄清一下会有帮助的。值得一提的是,查看ListBox源代码,您可以看到Add方法没有调用Sort,它只是调用(内部)BinarySearch方法来获取放置新项的索引。所以重写sort不会有帮助。但是为什么要对列表框进行排序呢。对我来说,列表框是用来显示数据而不是排序数据的。如果要排序,请将数据放入列表中,对该列表进行排序,并将该列表绑定到ListBox。这种行为有很好的文档记录。这样工作有一个很好的理由,本地ListBox控件保留其自己的列表中显示的字符串副本。因此,为了对它们进行排序,必须首先清空该列表,然后按照排序顺序重新添加已排序的项。这是非常昂贵的,太昂贵了,不能每次添加一个项目时都这样做。@SergeyBerezovskiy这实际上与MSDN上的代码不同。但我明白你的意思,那篇文章其实并不需要它。
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);
    }
}