Voir le flux RSS

Blog de Serge Girard (aka SergioMaster)

[Actualité] [FMX] Sélection d'éléments dans un TListView - Bonus

Noter ce billet
par , 09/10/2019 à 16h49 (92 Affichages)
J'ai eu du mal à m'en empêcher, je ne voulais pas que le lecteur reste sur une fausse impression, à savoir que cela ne pouvait fonctionner qu'avec un TProtypeBindSource.

J'ai donc concocté un petit fichier XML à partir du fichier customers.xml des exemples de données fournis, bien choisi car les clients semblent être des écoles de plongée
Par l'intermédiaire d'un FDBatchMove je n'ai récupéré que les colonnes CustNo, Company et Country suffisant pour ma liste.
Pour traiter ce fichier j'utiliserai un TFDMemtable et y ait ajouté un index composé des colonnes Country et Company qui me permettra d'avoir une liste ordonnée.

Nom : optiondesign.PNG
Affichages : 28
Taille : 51,4 Ko

Comme il n'y avait que peu de nouveauté par rapport aux méthodes déjà exposées chapitre III dans du billet précédent je me suis attaché à la navigation au sein des éléments sélectionnés.

Pour se positionner sur le premier élément sélectionné, facile puisque l'on peut obtenir ce dernier par l'intermédiaire de la fonction FirstChecked(True)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
procedure TBonus.PremierClick(Sender: TObject);
begin
If ListViewReal.Items.FirstChecked(True)>-1
  then begin
     ListViewReal.BeginUpdate;
     ListViewReal.Selected:=ListViewReal.Items[ListViewReal.Items.FirstChecked(True)];
     ListViewReal.EndUpdate;
  end;
end;
Seule astuce à relever, il faut forcer un rafraichissement de la liste après positionnement (couple d'instruction encadrante BeginUpdate/EndUpdate) sous peine que la liste défile incorrectement (sauf si votre liste est synchronisée avec votre source de données).

Pour se déplacer en avant ou en arrière une seconde astuce consiste à obtenir la liste triée (elle l'est toujours) dans le bon sens, ce que permet la surcharge de la fonction CheckedIndexes(const AOrder : TListViewItems.TOrder; const AChecked: Boolean)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
procedure TBonus.PrécédentClick(Sender: TObject);
var CheckList : TArray<Integer>;
    Index, C : Integer;
begin
Index:=ListViewReal.Selected.Index;
CheckList:=ListViewReal.Items.CheckedIndexes(TListViewItems.TOrder.LastToFirst,True);
ListViewReal.BeginUpdate;
for C in CheckList do
  if C<Index then
    begin
     ListViewReal.Selected:=ListViewReal.Items[C];
     Break;
    end;
ListViewReal.EndUpdate;
end;

procedure TBonus.SuivantClick(Sender: TObject);
var CheckList : TArray<Integer>;
    Index, C : Integer;
begin
Index:=ListViewReal.Selected.Index;
CheckList:=ListViewReal.Items.CheckedIndexes(TListViewItems.TOrder.FirstToLast,True);
ListViewReal.BeginUpdate;
for C in CheckList do
  if C>Index then
    begin
     ListViewReal.Selected:=ListViewReal.Items[C];
     Break;
    end;
ListViewReal.EndUpdate;
end;
Cette première étape finie j'ai voulu abattre certaines remarques que j'avais pu faire sur l'entête de groupe et son apparence custom (mettre une image) et sur la possibilité de faire de cette liste une sorte de menu.
C'est chose faite. Oui, c'est possible, cela ne veut qu'il faut utiliser cette astuce pour tous vos menus, mais c'était trop tentant

Nom : Menu.PNG
Affichages : 26
Taille : 18,7 Ko

Pour ajouter une image, c'est dans l'évènement OnUpdateObject de la liste que je le code.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
procedure TBonus.ListViewMenuUpdateObjects(const Sender: TObject;
  const AItem: TListViewItem);
begin
if AItem.Purpose=TListItemPurpose.Header then
    AItem.Objects.ImageObject.Bitmap.LoadFromFile('..\..\fleche.png');
end;
Il y a d'autres possibilités de chargement de l'image, par exemple à partir d'un TImageList
Code : Sélectionner tout - Visualiser dans une fenêtre à part
 AItem.Objects.ImageObject.Bitmap:=ImageList1.Bitmap(TSizeF.Create(32,32),0);
je joue mon jocker pour l'utilisation d'image multi-résolution.

L'important est surtout la manière d'accéder à l'ImageObject

Réduire le groupe a été un peu plus décevant car il est impossible d'indiquer zéro ou un nombre négatif pour la hauteur d'un élément. Plus il y aura d'éléments, plus un gap gris, plus ou moins important selon le nombre d'éléments du groupe, apparaitra (dommage).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
procedure TBonus.ListViewMenuItemClick(const Sender: TObject;
  const AItem: TListViewItem);
var AnItem : TListViewItem;
    i : Integer;
begin
if AItem.Purpose=TListItemPurpose.Header then
 begin
   if AItem.Tag=0 then AItem.Tag:=1 else AItem.Tag:=0;     // mémorise si le groupe est ouvert ou fermé 
   for  I:= AItem.Index+1  to listviewmenu.items.count-1 do   
    begin
     AnItem:=ListViewMenu.Items[i];
     if AnItem.Purpose=TListItemPurpose.Header then Break;  
     if AItem.Tag=0 then AnItem.Height:=44 else AnItem.Height:=1;  // change la taille de l'élément
     AnItem.Objects.TextObject.Visible:=AItem.Tag=0;                     // texte invisible si groupe fermé
    end;
   AItem.Objects.ImageObject.Bitmap.Rotate(180);  // retourne l'image
 end;
end;
Vous retrouverez tout le code dans cette nouvelle archive en pièce jointe.
Miniatures attachées Fichiers attachés

Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Viadeo Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Twitter Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Google Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Facebook Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Digg Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Delicious Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog MySpace Envoyer le billet « [FMX] Sélection d'éléments dans un TListView - Bonus » dans le blog Yahoo

Mis à jour 11/10/2019 à 08h19 par SergioMaster (modification du zip)

Catégories
Delphi , FMX

Commentaires

  1. Avatar de SergioMaster
    • |
    • permalink
    Après avoir testé sous Ubuntu (cela fonctionne ) mais j'ai procédé à quelques changements au niveau du traitement de l'image, mise en ressource cela m'évite de déployer le fichier fleche.png ainsi que les problèmes de chemin de chargement c'est donc tout bénéfice.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    procedure TBonus.ListViewMenuUpdateObjects(const Sender: TObject;
      const AItem: TListViewItem);
    //  NOTE
    // il serait mieux de ne charger qu'une seule fois la ressource dans un Stream
    // de même s'il s'agit d'un fichier
    // d'où "l'avantage" de la liste d'image quoique, si l'on utilise un MultiResBitmap on se retrouvera dans le même cas
    var aStream: TResourceStream;
    begin
    // Chargement d'une ressource
    if AItem.Purpose=TListItemPurpose.Header then
      begin
         aStream := TResourceStream.Create(HInstance,'fleche',RT_RCDATA);
          try
            AItem.Objects.ImageObject.Bitmap.LoadFromStream(aStream);
         finally
           aStream.Free;
        end;
    // Chargement fichier "externe"
    //    AItem.Objects.ImageObject.Bitmap.LoadFromFile('..\..\fleche.png');
    // Utilisation TImageList
    //    AItem.Objects.ImageObject.Bitmap:=ImageList1.Bitmap(TSizeF.Create(32,32),0);
      end;
    end;
    Ces changements ont été répercutés dans le zip.