Just wanted To have an "ID" property on my Items, so i dont have to compare them by Name and detect wich item it is by Name. Is there any other (better) Component then ListBox ?
For me, the data and its representation should be separated.
Let's take, for example, some data:
type
TMyItem = record
Id: SizeInt;
Name: string;
end;
TMyItemArray = array of TMyItem;
And somehow initialize them:
procedure PrepareData(out Data: TMyItemArray);
const
CCount = 10000;
var
i: SizeInt;
N: SizeInt;
begin
SetLength(Data, CCount);
for i := 0 to CCount - 1 do
begin
N := Random(CCount);
Data[i].Id := N;
Data[i].Name := Format('Item %.4d', [N]);
end;
end;
To represent the data, we take TListView in virtual mode:
procedure PrepareListViewAsVirtual(AListView: TListView; ACount: SizeInt);
begin
AListView.ColumnClick := False;
AListView.HideSelection := False;
AListView.OwnerData := True;
AListView.ReadOnly := True;
AListView.RowSelect := True;
AListView.ShowColumnHeaders := False;
AListView.ViewStyle := vsReport;
AListView.Columns.Add;
AListView.Items.Count := ACount;
end;
Now let's link the data to the view:
TForm1 = class(TForm)
ListView1: TListView;
...
private
FData: TMyItemArray;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
PrepareData(FData);
PrepareListViewAsVirtual(ListView1, Length(FData));
end;
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem); // OnData Event
var
i: SizeInt;
begin
i := Item.Index;
if Math.InRange(i, 0, High(FData)) then
Item.Caption := FData[i].Name;
end;
For a better display, we'll adjust it a little:
procedure TForm1.FormShow(Sender: TObject);
begin
ListView1.AutoWidthLastColumn := True;
if ListView1.ItemIndex < 0 then
ListView1.ItemIndex := Low(FData);
end;
Now, suppose we want to sort the array by ID. Let's use STL garrayutils unit:
type
TMyItemSortWrapper = record
class function c(const Left, Right: TMyItem): Boolean; static; // Left < Right
end;
class function TMyItemSortWrapper.c(const Left, Right: TMyItem): Boolean;
begin
Result := Left.Id < Right.Id;
end;
{$PUSH}
{$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined}
procedure SortDataById(var Data: TMyItemArray);
type
TSorter = specialize TOrderingArrayUtils<TMyItemArray, TMyItem, TMyItemSortWrapper>;
begin
TSorter.Sort(Data, Length(Data));
end;
{$POP}
And assign the sorting to some button:
procedure TForm1.Button1Click(Sender: TObject);
begin
SortDataById(FData);
ListView1.Refresh;
end;
To see all this in action, create an empty project, add a ListView and a Button to the Form. Add the code specified above to the desired events.
Don't forget to specify {$MODESWITCH ADVANCEDRECORDS} in the header and add "uses Math, garrayutils" in the implementation.