如何用TListView来处理大量数据
采用常规方法处理ListView,在数据量大时无论是还是用了BeginUpdata和EndUpdata()
还是处理WM_EraseBkgnd信息都不会得到理想的效果,那答案是什么呢?嗯,
采用所谓Virtual ListView技术。说起来很神秘,其实点通了很简单。
通常ListView中的所有数据都是由ListView自己来管理的,它负责这些数据空间的分配和释放,
当你把ListView->OwnerData设为true时,ListView就把数据的管理权交给了你,而它只负责显示。
这时你需要自己来为数据分配和释放空间,至于你怎样来管理这些数据完全有你自己来定,
ListView完全不关心,当ListView需要显示某条数据时,它就调用OnData事件,
你只要在这个事件的处理函数里指定ListView即将显示的Item的内容就可以了。
这就是所谓的Virtual ListView技术。
由于ListView对数据管理的功能强大,随之而来的却是效率低下,
如果你采用更高效的数据管理方式就会极大的改变效率。
而且Virtual ListView只在数据需要显示时才调用OnData事件载入数据,所以速度很快。
下面的例子中,假设ListView中需要显示4列数据,所有的数据被保存在vector里。
/*Unit1.h*/
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <vector.h>
using namespace std;
//---------------------------------------------------------------------------
struct ListViewData //用于存储一条数据的结构体
{
AnsiString Caption;
AnsiString SubItems1;
AnsiString SubItems2;
AnsiString SubItems3;
};
class TForm1 : public TForm
{
__published: // IDE-managed Components
TListView *ListView1;
void __fastcall ListView1Data(TObject *Sender, TListItem *Item);
private: // User declarations
vector<ListViewData*> m_lvDataVector; //用于存储所以数据的向量
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
/*unit1.cpp*/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ListView1->OwnerData = true;
const int iListViewCount = 5000;
ListView1->Items->Count = iListViewCount; //必须指定,以使ListView知道其虚拟数据量
//保存数据
for(int i = 0; i < iListViewCount; ++i) {
ListViewData *plvData = new ListViewData;
plvData->Caption = "Caption" + AnsiString(i);
plvData->SubItems1 = "SubItems1" + AnsiString(i);
plvData->SubItems2 = "SubItems2" + AnsiString(i);
plvData->SubItems3 = "SubItems3" + AnsiString(i);
m_lvDataVector.push_back(plvData); //向vector中添加一项
}
}
__fastcall TForm1::~TForm1()
{
int iCount = ListView1->Items->Count;
for(int i = 0; i < iCount; ++i) {
ListViewData *plvData = m_lvDataVector[i];
delete plvData; //释放数据占用的资源
}
m_lvDataVector.clear(); //清空vector中所有条目
}
//---------------------------------------------------------------------------
//ListView在要显示某条数据时会调用这个函数
void __fastcall TForm1::ListView1Data(TObject *Sender, TListItem *Item)
{
if(Item->Index > m_lvDataVector.size())
return;
ListViewData *plvData = m_lvDataVector[Item->Index];
//指定要显示的条目的数据
Item->Caption = plvData->Caption;
Item->SubItems->Add(plvData->SubItems1);
Item->SubItems->Add(plvData->SubItems2);
Item->SubItems->Add(plvData->SubItems3);
}
//---------------------------------------------------------------------------
速度很快,5000条数据只要1秒左右.
在使用Virtual ListView方式时,如果要对数据排序,只需对你保存的内部数据(这里时vector对象)排序,然后ListView->Refresh()即可。这时你在ListView中看到的数据就是排好序的数据了。
Listview的高级应用
最新推荐文章于 2021-05-25 20:18:00 发布