Recent

Author Topic: ListView Drag Drop  (Read 1394 times)

Weitentaaal

  • Full Member
  • ***
  • Posts: 185
ListView Drag Drop
« on: May 05, 2021, 07:59:23 am »
Hello guys :)

So through my Prev. Post : https://forum.lazarus.freepascal.org/index.php/topic,54449.msg404533.html#msg404533
I was able to Separate Data and Gui but didn't managed to implement this with Drag and Drop. I Know how to make 2 ListViews able to drag and drop but i dont get it how u match ID's of my items with ItemIndex of ListView and how do i Display those Items the correct way ?

With Separation in those 2 ListViews i ment Something like :

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.ListView2Data(Sender: TObject; Item: TListItem);
  3. var
  4.   i: SizeInt;
  5. begin
  6.   i := Item.Index;
  7.  
  8.     IF (FData[i].aProperty = ThisandThisState) then begin
  9.         //Add To This List
  10.     end else begin
  11.         //Add to other list
  12.     end;
  13. end;
  14.  
« Last Edit: May 05, 2021, 03:49:31 pm by Weitentaaal »
Lazarus: 2.0.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

ASerge

  • Hero Member
  • *****
  • Posts: 1796
Re: ListView Drag Drop
« Reply #1 on: May 05, 2021, 02:36:00 pm »
A little slurred, I don't understand what is needed.
First, I will answer the last question from a closed topic. Why virtual? So that the data representation component does not waste its memory. In addition, it will exclude all sorts of "phantoms".

As far as I understand, you have two ListViews of the data. If you want to use a single data source (FData), then you need a selection criterion. If not, I don't see the problem: when dragged the data from FData1 (the indexes of the selected elements are the indexes in the data array), move it to FData2, and then adjust the number of elements in the virtual Listviews.

Weitentaaal

  • Full Member
  • ***
  • Posts: 185
Re: ListView Drag Drop
« Reply #2 on: May 05, 2021, 03:14:47 pm »
What i ment was that i  have 2 Lists.

1 Displays All Items wich are here and if u drag it to the Second it wont be Displayed anymore at First List.
It's like a Checkstate (First List unchecked second checked). So i thought i use a Data Array wich i get from my Database, in wich all of my items are represented.

I Have a Property (boolean) wich will provide me info about the "checkstate" of the Item if True then it should get Displayed in Second Form, if False then in the First.

In Short: 2 ListViews, 1 Data Array (How do i provide ListViews with info and make those basic operations (Add, Delete, Edit(Data), Put item from 1 list in the other))
But i don't realy get it how i should do the Data Linking. Pls Help Thanks
« Last Edit: May 05, 2021, 03:39:22 pm by Weitentaaal »
Lazarus: 2.0.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

y.ivanov

  • Full Member
  • ***
  • Posts: 125
Re: ListView Drag Drop
« Reply #3 on: May 05, 2021, 05:21:15 pm »
Since TListItem.Data is of type Pointer you should typecast:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ListView2Data(Sender: TObject; Item: TListItem);
  2. var
  3.   i: SizeInt;
  4. begin
  5.   //i := Item.Index;
  6.   i := PtrInt(Item.Data);
  7.  
  8.  

And when assigning to it:

Code: Pascal  [Select][+][-]
  1.   Item.Data := Pointer(PtrInt(i));
  2.  

as korba812 pointed out in: https://forum.lazarus.freepascal.org/index.php/topic,54449.msg404508.html#msg404508

Weitentaaal

  • Full Member
  • ***
  • Posts: 185
Re: ListView Drag Drop
« Reply #4 on: May 06, 2021, 07:39:15 am »
I Know how to cast thanks :)

How do i manage my Indexes ? My ID's should not change itself.

And why doesn't my ListView dispülay things when i set it to vsReport

Edit : Now using ListBox, works better. But i don't understand why i don't have to Free my Object before Deleting an item.

Code: Pascal  [Select][+][-]
  1.  
  2.    if (Source is TListBox)  and (TListBox(Source).ItemIndex > -1) then begin // Wenn der Objekttyp stimmt werden die Daten übernommen
  3.       Data := GetData(TListBox(Source).Items.Objects[TListBox(Source).ItemIndex]);
  4.       Data^.Ausgewaehlt:= True;
  5.  
  6.       ListBox2.Items.AddObject(Data^.Name, TObject(Data)); // Fügt den Text aus dem Edit hinzu
  7.  
  8.       TListBox(Source).Items.Delete(TListBox(Source).ItemIndex);
  9.    end;
  10.  

Do i have to Free The Object before Deleting Item ? bc when i did that i got an error now it works (i guess :-[). Or can i just delete item bc Object is used from another Item
« Last Edit: May 06, 2021, 09:44:48 am by Weitentaaal »
Lazarus: 2.0.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

y.ivanov

  • Full Member
  • ***
  • Posts: 125
Re: ListView Drag Drop
« Reply #5 on: May 06, 2021, 03:17:03 pm »
It may be easier to read that way:

Code: Pascal  [Select][+][-]
  1. var
  2.   LB: TListBox;
  3. begin
  4.   if (Source is TListBox) then
  5.     LB := TListBox(Source) else
  6.     Exit;
  7.  
  8.    if LB.ItemIndex > -1 then begin // Wenn der Objekttyp stimmt werden die Daten übernommen
  9.       Data := GetData(LB.Items.Objects[LB.ItemIndex]);
  10.       Data^.Ausgewaehlt:= True;
  11.  
  12.       ListBox2.Items.AddObject(Data^.Name, TObject(Data)); // Fügt den Text aus dem Edit hinzu
  13.  
  14.       LB.Items.Delete(LB.ItemIndex);
  15.    end;
  16.  

Do i have to Free The Object before Deleting Item ? bc when i did that i got an error now it works (i guess :-[). Or can i just delete item bc Object is used from another Item

I don't see freeing of objects in the snippet, as it should be. The creation/freeing of data is up to you and it is not related to AddObject/Delete in TListBoxes. Items.Object[] in the listboxes are just additional pointers to the data. Just be careful not to use this pointers after your data is freed.

Weitentaaal

  • Full Member
  • ***
  • Posts: 185
Re: ListView Drag Drop
« Reply #6 on: May 06, 2021, 03:53:58 pm »
Any idea how to iterate through 2 ListBoxes that way ?

Edit: Thought about Searching an Item through its ID or check if Item is in first or second Listbox. Is it possible to Create an Array or an object list wich stores all references to the object. Then use this List to Change Propertys of my Object (Will it change in the Listboxes to ? for example when i Store object of item 1 in a list, then change Propertys of Object in List (Example : Name), will it change the Name also in my ListBox ?). Or is there Something wich provides more control over those Items.
« Last Edit: May 06, 2021, 04:09:19 pm by Weitentaaal »
Lazarus: 2.0.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

y.ivanov

  • Full Member
  • ***
  • Posts: 125
Re: ListView Drag Drop
« Reply #7 on: May 06, 2021, 05:28:05 pm »
Any idea how to iterate through 2 ListBoxes that way ?

Edit: Thought about Searching an Item through its ID or check if Item is in first or second Listbox. Is it possible to Create an Array or an object list wich stores all references to the object. Then use this List to Change Propertys of my Object (Will it change in the Listboxes to ? for example when i Store object of item 1 in a list, then change Propertys of Object in List (Example : Name), will it change the Name also in my ListBox ?). Or is there Something wich provides more control over those Items.

I am not sure I can understand  :-[ It is true I'm not a native speaker, may be is the language barrier...

Weitentaaal

  • Full Member
  • ***
  • Posts: 185
Re: ListView Drag Drop
« Reply #8 on: May 06, 2021, 05:31:06 pm »
Sorry  :-[

I just wanted to know how to search for items in 2 ListBoxes. How can i go through 2 ListBoxes ?
Lazarus: 2.0.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

howardpc

  • Hero Member
  • *****
  • Posts: 3715
Re: ListView Drag Drop
« Reply #9 on: May 06, 2021, 05:53:08 pm »
A listbox is a visual control designed to hold a limited number of strings (and, optionally, objects associated with each string).
Searching for a particular string item is normally done by setting the listbox's Sorted property, and letting the user scroll to find the string she wants to select.
If you prefer to search programmatically, the listbox provides an indexed Items array property which you can enumerate between indexes 0 and Pred(listbox.Items.Count).
To search for an object associated with a string item, you can likewise enumerate the Items.Objects array property.
You can obviously enumerate the items of as many listboxes as you want.
Are you asking for example code to illustrate this?
« Last Edit: May 06, 2021, 05:55:29 pm by howardpc »

y.ivanov

  • Full Member
  • ***
  • Posts: 125
Re: ListView Drag Drop
« Reply #10 on: May 06, 2021, 06:01:30 pm »
Sorry  :-[

I just wanted to know how to search for items in 2 ListBoxes. How can i go through 2 ListBoxes ?

ListBox1.Items.Objects is an indexed property, you can iterate it with a for loop:

Code: Pascal  [Select][+][-]
  1. for I := 0 to ListBox1.Items.Count - 1 do
  2.     ...; // Do something with ListBox1.Items.Objects[I]
  3.  
I still don't understand what you are trying to achieve. You give very little information on each post.

speter

  • Full Member
  • ***
  • Posts: 209
Re: ListView Drag Drop
« Reply #11 on: May 07, 2021, 01:56:02 am »
I think the OP wants a function to search through 2 listboxes.

I suggest following y.ivanov's advice to iterate through the first listbox; if you find the item you are searching for set your return values (aka result) and exit; if you get to the end of the list (without finding the item); iterate through the second listbox...

The following is NOT tested ;)
Code: Pascal  [Select][+][-]
  1. type
  2.   Tinfo = record
  3.     list : TListBox;
  4.     itemnum : integer;
  5.   end;
  6.  
  7. function makeit(lb : TListBox; i : integer) : Tinfo;
  8. begin
  9.   result.list := lb;
  10.   result.itemnum := i;
  11. end;
  12.  
  13. function findit(thestring : string; listbox1,listbox2 : tlistbox) : Tinfo;
  14. var
  15.   i : integer;
  16. begin
  17.   for i := 0 to listbox1.items.count-1 do
  18.     if listbox1[i] = thestring then
  19.       exit(makeit(listbox1,i));
  20.  
  21.   for i := 0 to listbox2.items.count-1 do
  22.     if listbox2[i] = thestring then
  23.       exit(makeit(listbox1,i));
  24.  
  25.   result.list := nil;
  26.   result.itemnum := -1;
  27. end;
  28.  

cheers
S.
I climbed mighty mountains, and saw that they were actually tiny foothills. :)

Laz 2.0.10 / FPC 3.2.0 / Windows 10 (64bit)

Weitentaaal

  • Full Member
  • ***
  • Posts: 185
Re: ListView Drag Drop
« Reply #12 on: May 07, 2021, 07:43:34 am »
Thanks For all ur Reply's :)

Got this far now. Sorry for my Questions but i'm just trying to find good methodes to get better at Lazarus.

Got this right now:

Code: Pascal  [Select][+][-]
  1.  
  2. //Insert
  3. procedure readAccessoires();
  4. var
  5.    i : Integer;
  6.    Data : PSelectedZubehoer;
  7. begin
  8.    //ZubehoerListe Laden
  9.    dbExecute(RsZub, 'SELECT * FROM ZubehoerSW ORDER BY ID');
  10.  
  11.    BereSW.ZubListe1.Clear;
  12.    if (not RsZub.IsEmpty) then begin
  13.       RsZub.First;
  14.       while not(RsZub.EOF) do begin
  15.          Data := New(PSelectedZubehoer);
  16.          Data^.ID:= RsZub.FieldByName('ID').AsInteger;
  17.          Data^.Name:= RsZub.FieldByName(FeldD).AsString;;
  18.          Data^.Ausgewaehlt := False;
  19.  
  20.          BereSW.ZubListe1.Items.AddObject(Data^.Name, TObject(Data));
  21.          RsZub.Next;
  22.       end;
  23.    end;
  24.  
  25.    //Größte ID holen und von hier jezt die ID's für Selbst def. geben
  26.    dbExecute(RsZub, 'SELECT * FROM ZubehoerSW WHERE ID = (SELECT MAX(ID) FROM ZubehoerSW);');
  27.    Data := New(PSelectedZubehoer);
  28.    Data^.ID:= (RsZub.FieldByName('ID').AsInteger + 1);
  29.    //IF (RsCalc.FieldByName('Zubehoer' + (i + 1).ToString).AsString <> '') then Data^.Name:= RsCalc.FieldByName('Zubehoer' + (i + 1).ToString).AsString
  30.    {else} Data^.Name:= '...';
  31.    Data^.Ausgewaehlt := False;
  32.  
  33.    BereSW.ZubListe1.Items.AddObject(Data^.Name, TObject(Data));
  34. end;
  35.  
  36. //Insert with pre-set Values
  37. //String is Binary (Example: 101000101) 1 for checked 0 for unchecked
  38. procedure AccOfData(AccStr: String);
  39. var
  40.    N, i: Integer;
  41.    Data : PSelectedZubehoer;
  42. begin
  43.    laden:= True;
  44.  
  45.    //write all items in first box
  46.    For i := 0 to BereSW.ZubListe2.Items.Count do begin
  47.       Data:= Global.ZubGetData(BereSW.ZubListe2.Items.Objects[i]);
  48.       Data^.Ausgewaehlt:= False;
  49.  
  50.       Global.ZubChangeList(i, BereSW.ZubListe2, BereSW.ZubListe1);
  51.    end;
  52.  
  53.    //check if some items should get into second box
  54.    for N := 0 to BereSW.ZubListe1.Items.Count - 1 do begin
  55.       if(N > AccStr.Length) or (AccStr[N + 1] = '9')then begin
  56.          laden:= False;
  57.          BereSW.ZubListeClick(Nil);
  58.          Exit;
  59.       end;
  60.  
  61.       Data:= Global.ZubGetData(BereSW.ZubListe1.Items.Objects[N]);
  62.       if(AccStr[N + 1] = '1')then begin
  63.          Data^.Ausgewaehlt:= True;
  64.  
  65.          Global.ZubChangeList(N, BereSW.ZubListe1, BereSW.ZubListe2);
  66.       {end else begin
  67.          Data^.Ausgewaehlt:= False;
  68.  
  69.          Global.ZubChangeList(N, BereSW.ZubListe2, BereSW.ZubListe1);
  70.       }end;
  71.    end;
  72.  
  73.    BereSW.ZubListeClick(Nil);
  74.    laden:= False;
  75. end;
  76.  

@speter thanks for your Code, i will definitely try it out, but i'm not a great fan of creating a Record just for the Search  :-[.
Lazarus: 2.0.6 x86_64-win64-win32/win64
FPC-Version: 3.0.4
Compiler Version: 3.2.0

 

TinyPortal © 2005-2018