.net listView排序速度慢 描述

.net listView排序速度慢 描述,.net,winforms,sorting,listview,c++-cli,.net,Winforms,Sorting,Listview,C++ Cli,我正在编写应用程序,它使用的是listViewlistView是一个简单的列表视图,只有我通过继承listView打开了doubleBufer,在构造函数中我写了: this->DoubleBuffer = true; 因此,我在我的列表视图中有一些列,当我单击列时,我需要对列项目进行排序。当我有500个项目时一切正常,但当listView中的项目数超过50.000,我按column对其中的项目进行排序时,我的列表冻结了1分钟,应用程序停止响应。下面我给出了排序代码 排序代码 ref类域

我正在编写应用程序,它使用的是
listView
<我使用的code>listView是一个简单的列表视图,只有我通过继承
listView
打开了
doubleBufer
,在构造函数中我写了:

this->DoubleBuffer = true;
因此,我在我的
列表视图中有一些列,当我单击列时,我需要对列项目进行排序。当我有500个项目时一切正常,但当
listView
中的项目数超过50.000,我按column对其中的项目进行排序时,我的列表冻结了1分钟,应用程序停止响应。下面我给出了排序代码

排序代码
ref类域排序器:公共系统::集合::IComparer{
公众:
虚拟整数比较(系统::对象^x,系统::对象^y){
系统::Windows::窗体::ListViewItem ^lvi1=静态转换(o1);
系统::字符串^str1=lvi1->子项[列\域]->文本;
系统::Windows::窗体::ListViewItem ^lvi2=静态转换(o2);
系统::字符串^str2=lvi2->子项[列\域]->文本;
int结果=0;
if(lvi1->ListView->Sorting==System::Windows::Forms::SortOrder::升序)
结果=系统::字符串::比较(str1、str2);
else结果=系统::字符串::比较(str2,str1);
返回结果;
}
};
无效列单击()
{
listViewDomainsInfo->BeginUpdate();
listViewDomainsInfo->ListViewItemSorter=gcnew DomainSorter();
if(listViewDomainsInfo->排序==排序器::升序)
listViewDomainsInfo->Sorting=SortOrder::Descending;
else listViewDomainsInfo->Sorting=SortOrder::升序;
listViewDomainsInfo->EndUpdate();
}
问题:
如何提高
listView
排序的速度。(我知道我可以使用虚拟列表,但我不想)你能帮我让这段代码运行得更快吗?

如果你想要更快的排序,你不应该使用集成排序行为。 例如:

  • 重写排序提供程序以使用
    ListViewItem
    而不是
    Object
  • 自己分类项目
  • 然后调用
    listViewDomainsInfo->Items->Clear()
    listViewDomainsInfo->Items->AddrRange()

  • 这样做应该更快。另外请注意,在这种情况下,您应该手动恢复可见项目范围。

    如果您希望更快地排序,则不应该使用集成排序行为。 例如:

  • 重写排序提供程序以使用
    ListViewItem
    而不是
    Object
  • 自己分类项目
  • 然后调用
    listViewDomainsInfo->Items->Clear()
    listViewDomainsInfo->Items->AddrRange()

  • 这样做应该更快。还请注意,在这种情况下,您应该手动恢复可见项范围。

    要避免无响应的UI,您唯一能做的就是在另一个线程上对项列表进行排序(与
    列表视图分离)完成后,调用
    ListView.Items.Clear
    ListView.Items.AddRange
    将已排序的项目添加到
    ListView
    。不确定线程管理和同步的基础架构开销是否值得付出努力。

    避免无响应UI的唯一方法是对另一个线程上的项目列表进行排序(与
    列表视图分离)完成后,调用
    ListView.Items.Clear
    ListView.Items.AddRange
    将已排序的项目添加到
    ListView
    。不确定线程管理和同步的基础架构开销是否值得付出努力。

    您正在排序50000个项目。没有什么魔术能让它跑得更快。您已经知道解决方案--使用虚拟模式。这种情况正是它设计的目的。但是你不想使用它,所以不要期待任何奇迹,即使有人可以对你的排序代码做一些小的调整。非常感谢,我只是想知道是否有其他方法可以做到这一点!现在我知道没有了!!你认为我必须删除这个问题吗?你在整理50000个项目。没有什么魔术能让它跑得更快。您已经知道解决方案--使用虚拟模式。这种情况正是它设计的目的。但是你不想使用它,所以不要期待任何奇迹,即使有人可以对你的排序代码做一些小的调整。非常感谢,我只是想知道是否有其他方法可以做到这一点!现在我知道没有了!!您认为我必须删除此问题还是否?为什么使用
    ListVIewItem
    而不是
    Object
    会更快?它们都是参考类型;这里没有拳击比赛。他已经用
    BeginUpdate
    /
    EndUpdate
    暂停更新,所以用
    AddRange
    清除和添加项目的速度不太可能比他已经做的更快。我的一个项目(文件管理器)也有同样的问题。我用这种方法解决了这个问题。现在排序~20000只需不到1秒(请注意,我的排序更复杂)。因此,我可以保证Clear()+AddRange()比集成的ListView行为快得多。直接使用ListViewItem总是比将对象强制转换为ListViewItem快。为什么使用
    ListViewItem
    而不是
    Object
    更快?它们都是参考类型;这里没有拳击比赛。他已经用
    BeginUpdate
    /
    EndUpdate
    暂停更新,所以用
    AddRange
    清除和添加项目的速度不太可能比他已经做的更快。我的一个项目(文件管理器)也有同样的问题。我用这种方法解决了这个问题。现在排序~20000只需不到1秒(请注意,我的排序更复杂)。所以我可以保证Clear()+AddRange()非常
    ref class DomainSorter : public System::Collections::IComparer {
            public:
                virtual int Compare( System::Object^ x, System::Object^ y) {
                    System::Windows::Forms::ListViewItem^ lvi1 = static_cast<System::Windows::Forms::ListViewItem^>(o1);
                    System::String^ str1 = lvi1->SubItems[COLUMN_DOMAIN]->Text;
                    System::Windows::Forms::ListViewItem^ lvi2 = static_cast<System::Windows::Forms::ListViewItem^>(o2);
                    System::String^ str2 = lvi2->SubItems[COLUMN_DOMAIN]->Text;
    
                    int result = 0;
    
                    if( lvi1->ListView->Sorting == System::Windows::Forms::SortOrder::Ascending)
                         result = System::String::Compare( str1, str2 );
                    else result = System::String::Compare( str2, str1 );
    
                    return result;
                }
    
            };
    
    void OnColumnClick( )
    {
        listViewDomainsInfo->BeginUpdate( );
        listViewDomainsInfo->ListViewItemSorter = gcnew DomainSorter( );
        if (listViewDomainsInfo->Sorting == SortOrder::Ascending)
        listViewDomainsInfo->Sorting = SortOrder::Descending;
        else listViewDomainsInfo->Sorting = SortOrder::Ascending;
        listViewDomainsInfo->EndUpdate( ); 
    }