TListBox with Item ID's lazarus / 31-LCL ---------------------------------------------------------------------- Weitentaaal · 2021-05-04 06:49 Hello Guys Lately i was about to rewrite Some of my Code. I Had 2 ListBoxes where 1 should display all selected items and the other the non-selected items. All fine until i had to sort it by relevance. So i had to Idetnify my items so i could write a proper sorting logarithm for my items. Is it somehow possible to make something like this happen ?: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i      TSZ = Object      ID : integer;      Name : String;  end;  procedure TForm1.FormShow(Sender: TObject);var   sz : Array of TSZ;   Tests : TSZ;   i : Integer;begin   for i := 0 to 10 - 1 do begin      //Tests.setName('Test' + i.ToString);      //Tests.setID(i);      Tests.Name:= 'Test'+ i.ToString;      Tests.ID := i;      sz[i] := Tests;   end;    for i := 0 to SizeOf(sz) - 1 do begin      ListBox1.Items.AddObject(sz[i].Name, sz[i]);  //<--- Error   end;end;  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 ? ---------------------------------------------------------------------- alpine · 2021-05-04 09:08 You can use ListBox1.Items.AddObject() for that, just use proper type casting: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ListBox1.Items.AddObject(ItemName, TObject(ItemId)); // ItemId is an integer...ItemId := Integer(ListBox1.Items.Objects[index_of_item]);  Your sample code is wrong also for another reason - because you use local variable sz it will cease to exist when you exit the FormShow() method. If you decide to use Object[] property to point to something useful it must be allocated on heap or at least to be a pointer to a global variable. ---------------------------------------------------------------------- Weitentaaal · 2021-05-04 09:14 Illegal type conversion (Attached Picture of Errors) and btw. i "sz" is Global. This is just a new Project to test ListBox ---------------------------------------------------------------------- korba812 · 2021-05-04 09:22 If you are using the 64 bit compiler then you must first cast to the appropriate integer type. It is best to use PtrInt, which is defined separately for each platform. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ListBox1.Items.AddObject(ItemName, TObject(PtrInt(ItemId))); // ItemId is an integer...ItemId := PtrInt(ListBox1.Items.Objects[index_of_item]); ---------------------------------------------------------------------- ASerge · 2021-05-04 10:32 Quote from: Weitentaaal on May 04, 2021, 08:49:30 amJust 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TMyItem = record    Id: SizeInt;    Name: string;  end;   TMyItemArray = array of TMyItem; And somehow initialize them: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   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 Eventvar  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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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;begin  TSorter.Sort(Data, Length(Data));end;{$POP} And assign the sorting to some button: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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. ---------------------------------------------------------------------- Weitentaaal · 2021-05-04 10:42 @Korba812 and @y.ivanov with ur Suggestions it worked ! Thanks @ASerge Thanks for your reply  you are right data and gui should definitely be separated so i guess i will have a look at ur work. It realy looks easy and will also provide me a better overview. Thanks to all of u again Edit: Why do i need Advanced Records(Only for Sorting method ? wich i will write on my won so i dont have to use modeswitch ?) and Why should the list be virtual ? Edit2: is it possible to use listBox instead of listView ? ---------------------------------------------------------------------- Weitentaaal · 2021-05-04 13:38 What happens to the Item index when i implement a drag and drop. Will this still work wich drag and drop ? ---------------------------------------------------------------------- howardpc · 2021-05-04 13:42 Quote from: Weitentaaal on May 04, 2021, 12:42:04 pmEdit: Why do i need Advanced Records(Only for Sorting method ? wich i will write on my won so i dont have to use modeswitch ?) and Why should the list be virtual ? Edit2: is it possible to use listBox instead of listView ? Advanced records are needed only for the sorting record wrapper which contains a method. It is certainly possible to use a listbox. See the attached project which is an adaptation of ASerge's code. ---------------------------------------------------------------------- Weitentaaal · 2021-05-04 13:51 Yes thanks .. that was what i was looking for ? so my (hopefully) last question then is about doing this with DragDrop. I Have lets say 100 items wich will be initialized like we did in the First ListBox or Listview. But how do i keep my ID's correct when i drop some items from 1 into 2 . Is it possible to make a DataField  for both ListViews ? maybe witch a property wich tells if Parent is ListView 1 or 2. Thanks