Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switching from ListView to VirtualStringTree

I am trying to build my projects with a VirtualStringTree rather than a Listview, because of the vast speed difference. The thing is, even after looking thru the demo's, I just can't figure out exactly how I would use it as a ListView. Like, adding, deleting, and basically just working with ListView items is so easy, but when I look at the VT, it gets almost too complicated.

All I am looking for, is a VT that looks like a ListView, with subitems etc.

Here are some routines using the ListView, that I would like to use with VT (This is just a pseudo example:

procedure Add;
begin
  with ListView.Items.Add do
    Begin
      Caption := EditCaption.Text;
      SubItems.Add(EditSubItem.Text):
    End;

end;

Procedure ReadItem(I : Integer);
begin

   ShowMessage(ListView.Items[I].Caption);
   ShowMessage(ListView.Items[I].SubItems[0]);

end;

Of course, also the Delete function, but since thats like 1 line, I didnt bother :P

Could anyone maybe translate the above examples into using a ListView style VT?

Thanks!

like image 834
Jeff Avatar asked Jan 03 '11 17:01

Jeff


2 Answers

Just use your normal TListView, but use it in virtual mode.

It's really simple:

  1. Set the OwnerData property to true
  2. Implement the OnData event handler.

Sample implementation that shows a simple list of 3 rows:

Type TMyItem=record
  Item:String;
  SubItem:String;
end;

var Items:Array of TMyItem;

// set up some in-memory dataset.. choose your own layout
SetLength(Items,3);
Items[0].Item := 'foo1';
Items[0].SubItem := 'bar1';

Items[1].Item := 'foo2';
Items[1].SubItem := 'bar2';

Items[2].Item := 'foo3';
Items[2].SubItem := 'bar3';

// tell ListView1 how many items there are
ListView1.Items.Count := Length(Items); 

procedure TfrmMain.ListView1Data(Sender: TObject; Item: TListItem);
begin
  Item.Caption := IntToStr(Item.Index);
  Item.SubItems.Add( MyArray[Item.Index] );
  Item.SubItems.Add( UpperCase(MyArray[Item.Index]) );
end;

// Updating a value:
Items[1].Item := 'bzzz';
ListView1.Update;

That's all!

Some things to keep in mind:

  1. You don't call ListView1.Items.Add() anymore.
  2. You need to keep your own list of data somewhere in memory, or come up with the data in real-time, so you cannot 'store' data in the listview any longer.
  3. You need to set the items.count property, or you won't see anything.
  4. Call ListView1.Update() if something changes.
like image 173
Wouter van Nifterick Avatar answered Oct 27 '22 06:10

Wouter van Nifterick


Why don't you use a list view in virtual mode? That will look and feel right and perform great.

The Delphi TListView control is a wrapper around the Windows list view component. In its default mode of operation copies of the list data are transferred from your app to the Windows control and this is slow.

The alternative to this is known as a virtual list view in Windows terminology. Your app doesn't pass the data to the Windows control. Instead, when the control needs to display data it asks your app for just the data that is needed.

The Delphi TListView control exposes virtual list views by use of the OwnerData property. You'll have to re-write your list view code somewhat but it's not too hard.

I also offer a link to another question here that covered similar ground. Rather oddly, the accepted answer for that question talked about list boxes even though the question was about list view controls.

like image 32
David Heffernan Avatar answered Oct 27 '22 05:10

David Heffernan