覆盖的 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 没有任何支持绑定的内置集合类型并且本质上是排序的。
我正在尝试覆盖列表框中的排序方法以按降序排序。
代码:
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 没有任何支持绑定的内置集合类型并且本质上是排序的。