Recent

Author Topic: Calling Listview EditCaption, it happened that item selection got falsified  (Read 925 times)

d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
Somewhere within a listview WndProc (after having finished a context menu dialog), i do a call to a CustomListview Selected.EditCaption (Lazaraus 2.0.12 Windows x64).
- That worked flawlessly with Delphi 7
- This works flawlessly if the number of listview items (for which the contect menu did appear) is so small that all items do fit within the visible area of the listview
* If the number of items if higher so that not all items do fit within the visible areas, the following does happen: 
-  i did select for instance the second element in the list  ('abc.txt'),
-  the inplace editor does not open, but the selection shifts to the last elemen in the list ('zzz.txt').

I isolated the problem within listitem.inc as follows:
notice that i used some test variables for to show where the issue happens:

Code: Pascal  [Select][+][-]
  1. function TListItem.EditCaption: Boolean;
  2. var
  3.   LV: TCustomListView;
  4.   xx_before1, xx_before2: String; i_before1, i_before2: Integer;
  5.   xx_after1, xx_after2: String; i_after1, i_after2: Integer;
  6.   xx_after3, xx_after4: String; i_after3, i_after4: Integer;
  7. begin
  8.   LV := FOwner.FOwner;
  9.                  xx_before1 := LV.Selected.caption;  // contains 'aaa.txt', correct
  10.                  xx_before2 := self.caption;         // contains 'aaa.txt', correct
  11.                  i_before1 := LV.ItemIndex;         // contains (eg.) 2, correct  
  12.                  i_before2 := self.Index;            // contains (eg.) 2, correct      
  13.  
  14.   LV.Selected := Nil;           // First clear all selections,
  15.   LV.Selected := Self;          // then set this item as the only selected.
  16.  
  17.                  xx_after1 := LV.Selected.caption;   // contains 'zzz.txt', wrong (last element!)
  18.                  xx_after2 := self.caption;         // contains 'zzz.txt', wrong (last element!)
  19.                  i_after1 := LV.ItemIndex;          // contains (eg.) 52; wrong
  20.                  i_after2 := self.Index;            // contains (eg.) 52; wrong
  21.  
  22. // I try to fix it by another way to restore the previous selection:
  23.  
  24.        LV.Selected := LV.Items[i_before1];    // ****** This is my test for to fix ******
  25.  
  26. // This does restore the previous selected / single item correctly
  27.  
  28.                  xx_after3 := LV.Selected.caption;     // contains 'aaa.txt', correct again
  29.                  xx_after4 := self.caption;            // contains 'aaa.txt', correct again
  30.                  i_after3 := LV.ItemIndex;            // contains (eg.) 2, correct again  
  31.                  i_after4 := self.Index;              // contains (eg.) 2, correct again  
  32.  
  33.   if LV.ReadOnly or (LV.FEditor=nil) then
  34.     exit(false);
  35.   LV.ShowEditor;
  36.   Result:=true;
  37. end;
  38.  

So i'm pretty sure where the issues begins, but i don't understand fully why.
I assume , the selection restore via LV.Selected := Self might use a wrong pointer now who had been influenced by "LV.Selected := nil". (But why **only then when the number of items increases the visiible part of the listview** ?)

It seems that "Self" after the assignment " LV.Selected := Nil" is not the same as before, but is itself a victim of the operation.

Might thee somehing been missing (with regard to assure the selection) before the EditCaption began?

Lazarus 3.2  FPC 3.2.2 Win10 64bit

d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
Because nobody did respond, i try it again.
See the images attached:
1 - directly before setting Selected to nil, "Self" pointed correctly to an object having caption "abc.txt"
2 - directly after setting Selected to nil,  "Self" pointed wrongly to an object having caption "zzz.txt"
(which is the last, but not visible element in the list=.

So i would like to locally replace the restore method via "Self":
Code: Pascal  [Select][+][-]
  1. LV.Selected := Nil;
  2. LV.Selected := Self; // Self points to the wrong object
  3. //by something like (works fine):
  4.  LV.Selected := LV.Items[saveIndex];  // LV-Selected will be fine again
  5.  

Can anybody give an advice how i write a helper / cracker method for TListItem.EditCaption that is able to change that?


Lazarus 3.2  FPC 3.2.2 Win10 64bit

d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
Found it. It's due to the property MultiSelect.

In my use case: although i allow the call to EditCaption only if one single item is selected.  TCustomListView.SetSelection does query the property MultiSelect - instead of SelCount > 1 ! - for to clear then the selection list.
So that it is not possible anymore to restore the last selected element in TListItem.EditCaption via LV.Selected := Self.

Either
-  querying for SelCount > 1 (instead of MultiSelect) in TCustomListView.SetSelection
-  or restoring a previously selected element via it's remembered index in TListItem.EditCaption
 would have fully sufficient to prevent the issue.

Maybe somebody might explain why this implementation is chosen using the query of MultiSelect and restore via Selected:=Self ? Is there a special meaning behind?

So, i would not call it a solution, but a workaround to temporarely switch off the MultiSelect before calling EditCaption.
Lazarus 3.2  FPC 3.2.2 Win10 64bit

 

TinyPortal © 2005-2018