none
[XAML] Definir largeur auto pour ListBoxItems orientés horizontalement

    Question

  • Bonjour,

    J'ai le plaisir de suivre l'excellent cours de Bob Tabor sur le développement d'applications universelles, et me penche actuellement sur la création d'un menu d'entête illustré comme ci-dessous :

    L'énoncé de cet exercice indique d'utiliser une grille de 4 colonnes de tailles dynamique, seulement je trouve plus pertinent d'utiliser une ListBox, permettant de gérer l'effet de sélection (survol, sélectionné..).

    Après quelque recherches, j'essai de m'approcher de la solution avec le code non fonctionnel suivant :

    <ListBox>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBoxItem>Donuts</ListBoxItem>
        <ListBoxItem>Coffee</ListBoxItem>
        <ListBoxItem>Schedule</ListBoxItem>
        <ListBoxItem>Complete</ListBoxItem>
    </ListBox>

    Ici, pas moyen d'accéder à la propriété Grid dans un ListBoxItem (d'ailleurs pourquoi ?), et je suis à court d'idées.

    Si il est toujours possible de le réaliser dans cette voie là (avec une ListBox), merci de m'en faire part.

    mercredi 27 décembre 2017 11:49

Toutes les réponses

  • Bonjour Ferrec Romain,

    C'est au sein de votre DataTemplate qu'il faut gérer les données à afficher. Vous devriez modifier l'ItemsTemplate au lieu du PanelTemplate

    Cordialement, 

    mercredi 27 décembre 2017 12:06
  • Bonjour Arthur Lemeur,

    Vous avez raison, le DataTemplate me permet de lier les éléments de la ListBox aux colonnes de la Grid. Bon j'essai de comprendre les choses au mieux à mon niveau, par l'exemple l'utilité du DataTemplate et cette notion de personnaliser l'affichage des données, mais chaque choses en son temps.

    Cela dit, j'en arrive au code suivant (inspiré de l'exemple de la documentation sur le DataTemplate :

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="100" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <!-- Menu -->
        <ListBox>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0">Donuts</TextBlock>
                        <TextBlock Grid.Column="1">Coffee</TextBlock>
                        <TextBlock Grid.Column="2">Schedule</TextBlock>
                        <TextBlock Grid.Column="3">Complete</TextBlock>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

    Mais les éléments ne s'affichent pas, seule la ListBox est visible dans le concepteur graphique (et même en exécution).


    mercredi 27 décembre 2017 13:52
  • L'ItemPlate représente le modèle d'affichage d'un élément de votre ListBox. 

    Ici vous avez bien définie un itemtemplate mais votre ListBox n'affiche aucune élément ! Vous devriez procéder ainsi : 

    <!-- Menu -->
            <ListBox>
                <ListBox.ItemTemplate>
                    <DataTemplate x:DataType="x:String">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0">{x:Bind}</TextBlock>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
    
                <ListBoxItem>Donuts</ListBoxItem>
                <ListBoxItem>Coffee</ListBoxItem>
                <ListBoxItem>Schedule</ListBoxItem>
                <ListBoxItem>Complete</ListBoxItem>
            </ListBox>

    En utilisant les bindings dans le DataTemplate, vous pouvez récupérer la valeur du ListBoxItem est le mettre dans votre présentation visuelle. 

    Cordialement, 

    mercredi 27 décembre 2017 14:09
  • Ah oui je viens de comprendre ! Pour chaque ListBoxItem (idéalement une entité de modèle), on lui applique le traitement définit dans le DataTemplate. Je pensais qu'il s'appliquait à l'ensemble des données et non un par un.

    Du coup cette piste ne me semble pas appropriée car je n'affiche que du texte simple. C'est ce texte que j'aimerais placer dans les cellules de la Grid (faisant office de menu), or dans votre code on place tous les éléments de liste sur la colonne 0.

    Après il est possible que le choix d'une ListBox est inappropriée dans ce cas, j'ai appris à l'utiliser dans une SplitView pour un menu latéral, et pensais qu'il aurait son utilité ici également.

    mercredi 27 décembre 2017 15:32