Bundles de type liste : SubCellView dans ListViewCell

0000003092     -      01/09/2023

MercatorPenguin 2.10.6.0 ou ultérieur permet d'inclure une SubCellView dans le paramétrage XAML de la ListViewCell d'un bundle de type "Liste". Cette SubCellView  permet d'afficher un carrousel horizontal ou une sous-liste verticale reprenant des informations "enfants" de la ListViewCell. Le nombre de cellules dans le carrousel n'est pas limité.

Une étape de bundle contenant une SubCellView doit donc contenir une requête SQL qui renvoie 2 dataTables :

  • la première avec les données parent de la ListViewCell (comme habituellement),
  • la seconde avec les données enfants de toutes les SubCellViews.

Une SubCellView est liée à sa ListViewCell parente par deux propriétés obligatoires :

  • ForeignKey : nom de la colonne dans la dataTable 2 qui va permettre la relation entre les deux dataTables
  • ParentPrimaryKey : nom de la colonne dans la dataTable 1 qui va permettre la relation entre les deux dataTables

Note : ces colonnes ne doivent pas nécessairement correspondre à une foreign key et une primary key dans la base de données, mais doivent permettre d'établir une relation entre les données extraites. Ces colonnes doivent être de type char ou varchar. Ces deux propriétés ne sont pas sensibles à la casse.

Nous reprenons ci-dessous une adaptation du bundle Consultation articles qui montre la mise en place d'une SubCellView.

SubCellView

La requête SQL est adaptée pour fournir 2 dataTables. La seconde exploite les données de ARTLIENS pour montrer dans le bundle les articles liés à l'article parent.

if @key=''
raiserror('Il faut spécifier une clé de recherche !',16,1 )

declare @cle1Lib char(250), @cle2Lib char(250), @cle3Lib char(250)

select @cle1Lib = isnull(rtrim(valeur),'Clé 1') from options where type = 'CLE1_S_F'


select dbo.XDESIGN_F(s_id) as modele,rtrim(@cle1Lib)+' : '+rtrim(s_cle1) as s_cle1,'Prix HTVA : '+ltrim(dbo.transform(s_prix_ht,'999 999.99')) as s_prix_ht,s_memo,s_id 
into #tmp
from STOCK 
where ((s_modele like '%'+@key+'%') or (s_cle1 like '%'+@key+'%') or (s_cle2 like '%'+@key+'%') or (s_cle3 like '%'+@key+'%')) and (s_sommeil=0)

select * from #tmp order by modele

select dbo.XDESIGN_F(artliens.id_lien) as modele,rtrim(@cle1Lib)+' : '+rtrim(s_cle1) as s_cle1,artliens.id_art,artliens.id_lien as s_id 
from #tmp inner join ARTLIENS on #tmp.s_id=artliens.id_art
order by modele

drop table #tmp

 

Le code XAML de la ListViewCell est :

<Label Text="@MODELE" Font="Medium" />
<Label Text="@S_CLE1" Font="Small" />
<Label Text="@S_PRIX_HT" Font="Small" />
<Label FormattedText="@S_MEMO" Font="Small" />

<m:SubCellView ItemsLayout="HorizontalList" HorizontalScrollBarVisibility="Always" HeightRequest="175" Margin="10,0,0,15" ForeignKey="id_art" ParentPrimaryKey="s_id">
<CollectionView.ItemTemplate>
    <DataTemplate>
        <Grid WidthRequest="380">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <m:Image Table="STOCK" Index="S_ID" Value="{Binding .[S_ID]}" Field="S_IMAGE1" Aspect="AspectFit" HeightRequest="150" WidthRequest="150" VerticalOptions="Center" Grid.Column="0" />
            <StackLayout VerticalOptions="FillAndExpand" Grid.Column="1">
                <StackLayout>
                    <Label Text="{Binding .[MODELE]}" FontSize="Medium" FontAttributes="Bold" LineBreakMode="WordWrap" Margin="10,0,0,0" />
                    <Label Text="{Binding .[S_CLE1]}" FontSize="Small" Margin="10,10,0,0" />
                    <BoxView HeightRequest="2" Margin="10,15,150,0" BackgroundColor="%ThemeColor%" />
                </StackLayout>
            </StackLayout>
        </Grid>
    </DataTemplate>
</CollectionView.ItemTemplate>
</m:SubCellView>

 

Dans une SubCellView, le dataBinding ne se fait pas via @NOM_DE_COLONNE mais avec l'expression {Binding .[NOM_DE_COLONNE]}. Le nom de colonne est toujours en majuscules. Hormis cette différence, tous les contrôles habituellement utilisés dans le code XAML de la ListViewCell peuvent aussi être utilisés dans la SubCellView.

Il n'est autorisé de placer qu'une seule SubCellView par ListViewCell.


Modification du comportement "étape suivante"

Un tap sur une cellule de la ListView permet de passer à l'étape suivante du bundle, en spécifiant en tant que paramètres SQL toutes les valeurs de la dataRow sélectionnée. Ceci permet d'afficher un niveau de détail supplémentaire (comportement habituel d'un bundle de type "Liste").

Lorsqu'on clique sur une cellule du carrousel, ce même comportement s'applique mais, si la cellule cliquée comprend des paramètres SQL de même nom que ceux de la ListViewCell parente, alors les valeurs de la SubCellView remplacent celles de la ListViewCell. Cela permet donc de se diriger vers le niveau de détail supplémentaire mais pour l'élément sélectionné dans le carrousel.

Par exemple (voir illustration ci-dessus) : la ListViewCell "Abricot" montre 3 articles liés ("Artichaut", "Café Java" et "Concombre"). Si l'utilisateur clique sur la cellule "Café Java", il recevra le détail de "Café Java" et non de "Abricot".


LSubCellView est une Xamarin.Forms.CollectionView. Il est dès lors possible d'utiliser les propriétés de cette classe de base.


Le bundle illustré ici peut être téléchargé : Consultation articles - test SubCellView.pngb

A l'étape 2, il montre une autre implémentation d'une SubViewCell avec la liste des dernières ventes.

SubViewCel2

 

declare @cle1Lib char(250), @cle2Lib char(250), @cle3Lib char(250)

select @cle1Lib = isnull(rtrim(valeur),'Clé 1') from options where type = 'CLE1_S_F'
select @cle2Lib = isnull(rtrim(valeur),'Clé 2') from options where type = 'CLE2_S_F'
select @cle3Lib = isnull(rtrim(valeur),'Clé 3') from options where type = 'CLE3_S_F'
 
select dbo.XDESIGN_F(s_id) as modele,
rtrim(@cle1Lib)+' : '+rtrim(s_cle1) as s_cle1,
rtrim(@cle2Lib)+' : '+rtrim(s_cle2) as s_cle2,
rtrim(@cle3Lib)+' : '+rtrim(s_cle3) as s_cle3,
'Prix HTVA : '+ltrim(dbo.transform(s_prix_ht,'999 999.99')) as s_prix_ht,
'DPA : '+ltrim(dbo.transform(s_dpa,'999 999.99')) as s_dpa,
'Stock : '+ltrim(dbo.transform(dbo.XDISPO_DISPO(s_id,'0000000001'),'999 999')) as dispo,
s_id
from STOCK 
where s_id=@s_id

select top 20 id_article,convert(char(10),pieds_v.date,105) as date,
rtrim(cli.c_nom)+ ' ('+rtrim(cli.c_ville)+')' as client,
'Q : '+ltrim(dbo.transform(lignes_v.q,'999 999')) as q,
'Tot Net HT : '+ltrim(dbo.transform(lignes_v.TOT_NET_HT,'999 999.99')) as tot_net_ht
from PIEDS_V inner join LIGNES_V on (pieds_v.id=lignes_v.id) and (pieds_v.journal=lignes_v.journal) and (pieds_v.piece=lignes_v.piece)
inner join CLI on (pieds_v.id_cli=cli.c_id)
where id_article=@s_id
order by pieds_v.date desc

 

<Label Text="@MODELE" Font="Medium" />

<Grid RowSpacing="10" ColumnSpacing="10" VerticalOptions="EndAndExpand" Margin="10,0,0,0">
<Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="20" />
        <RowDefinition Height="20" />
<RowDefinition Height="20" />
    </Grid.RowDefinitions>
<Label Text="@S_CLE1" Font="Small" Grid.Column="0" Grid.Row="0" LineBreakMode="TailTruncation" />
<Label Text="@S_CLE2" Font="Small" Grid.Column="0" Grid.Row="1" LineBreakMode="TailTruncation" />
<Label Text="@S_CLE3" Font="Small" Grid.Column="0" Grid.Row="2" LineBreakMode="TailTruncation" />
<Label Text="@S_PRIX_HT" Font="Small" Grid.Column="1" Grid.Row="0" />
<Label Text="@S_DPA" Font="Small" Grid.Column="1" Grid.Row="1" />
<Label Text="@DISPO" Font="Small" Grid.Column="1" Grid.Row="2" />
<Label Text="Dernières ventes" TextColor="%ThemeColor%" Font="Small" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" Margin="0,15,0,0" />
</Grid>

<m:SubCellView ItemsLayout="VerticalList" VerticalScrollBarVisibility="Always" Margin="60,0,0,0" ForeignKey="id_article" ParentPrimaryKey="s_id" >
<CollectionView.ItemTemplate>
    <DataTemplate>
<StackLayout>
        <Label Text="{Binding .[DATE]}" Font="Small" TextColor="%ThemeColor%" />
<Label Text="{Binding .[CLIENT]}" Font="Small" />
<StackLayout Orientation="Horizontal" Margin="10,0,10,0">
<Label Text="{Binding .[Q]}" Font="Small" />
<Label Text="{Binding .[TOT_NET_HT]}" Font="Small" Margin="25,0,0,0" />
</StackLayout>
</StackLayout>
    </DataTemplate>
</CollectionView.ItemTemplate>
</m:SubCellView>

Limitations

  • Une seule SubCellView est autorisée dans le code XAML ListViewCell.
  • Le nombre d'éléments dans une SubCellView n'est pas limité. Toutefois, il faut prendre en compte le fait qu'un très grand nombre d'éléments peut grever de façon importante les performances de l'application.
  • Le carrousel horizontal devra être préféré à la sous-liste horizontale, car en principe, l'environnement ne permet pas d'avoir deux éléments scrollables verticalement imbriqués.
  • Sous iOS, le SubCellView doit être le dernier élément du code XAML ListViewCell ou être le dernier élément d'un StackLayout.