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

时间:2015-06-02 16:22:28

标签: c# winforms sorting listbox

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

代码:

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/并且它说“不要忘记Sort只在Sorted属性从false变为true时调用”这对我来说似乎很荒谬,但果然,当切换Sorted和时回来,我的自定义排序被调用并运行。

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

我甚至会解决使用Sorted = false的hacky解决方案; Sorted = true;在ItemsChanged的事件处理程序中,但这样的事件不存在。

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

(我已经看过C#'s ListBox doesn't see my overrided Sort() method,但他的问题不明确,似乎只是“消失了”,他随机选择的答案并不理想,甚至可以通过无法获得的保护级别进行编译)

1 个答案:

答案 0 :(得分:1)

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

  

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

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

这就是为什么添加项目会导致它们根据默认实现进行排序。但它没有使用"基本Sort()方法" 来执行此操作。

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

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

您可以(根据评论中的建议)将已排序的集合绑定到ListBox,但这会更有效,特别是因为AFAIK没有任何内置集合支持绑定的类型以及固有排序的类型。