我正在尝试覆盖列表框中的排序方法以按降序排序。
代码:
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,但他的问题不明确,似乎只是“消失了”,他随机选择的答案并不理想,甚至可以通过无法获得的保护级别进行编译)
答案 0 :(得分:1)
您似乎明白要调用Sort()
方法,ListBox.Sorted
属性需要转换为true
。这是有记录的,虽然很差。据我所知,这是唯一一次调用Sort()
方法,这种理解与文档一致。
有趣的是,在此之后,保留Sorted = true,添加的新项目使用基础Sort()方法进行排序,创建升序和降序项目的混合。直到你切换Sorted false - >再次成真。
当您向ListBox
添加项目时,订单不是由Sort()
方法处理,而是由控件的集合对象处理。此对象执行二进制搜索以查找插入新项目的正确位置。不幸的是,在列表框项目文本中使用字符串比较是硬编码的。
这就是为什么添加项目会导致它们根据默认实现进行排序。但它没有使用"基本Sort()
方法" 来执行此操作。
对于Winforms ListBox
类,如果您想要有效排序的项目,最好的选择可能是不要覆盖Sort()
,也不要使用Sorted
属性。相反,提供一个辅助方法来添加新项目,并让该方法在Items
集合上进行适当的二进制搜索,以找到插入位置。
无论如何,您必须实现一个帮助方法来获取正在添加的项目的通知,并且执行已排序的插入比在每次插入时重新排序整个集合更有效。
您可以(根据评论中的建议)将已排序的集合绑定到ListBox
,但这会更有效,特别是因为AFAIK没有任何内置集合支持绑定的类型以及固有排序的类型。