web-dev-qa-db-fra.com

Ajouter plusieurs étiquettes dans Xamarin Forms

J'ai l'étiquette suivante:

<Label Text="{x:Static local:FontAwesome.FACheck}" FontFamily="FontAwesome" TextColor="Green"/>

Et un événement sur le bouton: 

correctButton.Clicked += (sender, e) =>
{
   App.DB.IncrementScore();
};

C’est que chaque fois que je clique sur un bouton, mon score est incrémenté de 1. Ce que je voulais faire, c’est aussi incrémenter le nombre de Labels en fonction du nombre de scores. Voir l'image ci-dessous:

 enter image description here

Quelqu'un a une idée de comment je pourrais y arriver? 

16
user6742877

Il existe différentes solutions à cette question. Assurez-vous de les lire tous avant de choisir celui-ci - mon préféré (le plus simple) est répertorié de haut en bas ...

Approche n ° 1:

Comme plusieurs personnes l'ont suggéré, vous pouvez créer un contrôle de collection (j'y reviendrai dans un instant), définir une ObservableCollection dans un ViewModel, définir le Binding Context de la page sur une instance de ce ViewModel et ajouter des éléments à la collection sur le bouton Cliquez sur:

public class MyViewModel()
{
    public ObservableCollection<int> Items { get; set; } = new ObservableCollection<int>();
}

private MyViewModel _viewModel = new MyViewModel();
public MainPage()
{
    InitializeComponent();

    BindingContext = _viewModel;
}

correctButton.Clicked += (sender, e) =>
{
    App.DB.IncrementScore();
    _viewModel.Items.Add(0);
};

Le type de ObservableCollection n'a pas d'importance, car nous utilisons la même valeur statique ItemTemplate pour tous les éléments:

<ContentPage.Resources>
    <DataTemplate x:Key="ScoreItemTemplate">
        <ViewCell>
            <ViewCell.View>
                <Label Text="{x:Static local:FontAwesome.FACheck}" FontFamily="FontAwesome" TextColor="Green"/>
            </ViewCell.View>
        </ViewCell>
    </DataTemplate>
</ContentPage.Resources>

Le principal problème de cette approche est que Xamarin.Forms ListView ne peut pas afficher ses éléments horizontalement. Cela signifie que vous devez télécharger l’un des packages HorizontalListView Nuget disponibles ou utiliser le intégré (uniquement dans Xamarin.Forms 2.3 et versions ultérieures!) CarouselView :

<CarouselView ItemTemplate="{StaticResource ScoreItemTemplate}" ItemsSource="{Binding Items}"/>

Ensuite, vous voudrez peut-être passer un certain temps à supprimer tous les effets visuels nécessaires pour faire défiler le carrousel et pour sélectionner des éléments si vous choisissez d'utiliser un ListView horizontal ...

Au lieu de cela, il existe deux solutions alternatives qui impliquent moins d'effort:

Approche n ° 2:

Évidemment, l’approche simple consisterait à créer l’étiquette "template" dans le code:

private Label CreateScoreLabel()
{
    return new Label {Text = FontAwesome.FACheck, TextColor = Color.Green, FontFamily = "FontAwesome"};
}

... ajoutez une StackLayout horizontale à la page:

<StackLayout Orientation="Horizontal" x:Name="LabelStack"/>

... et ajouter de nouvelles étiquettes à la dure:

correctButton.Clicked += (sender, e) =>
{
    App.DB.IncrementScore();
    LabelStack.Children.Add(CreateScoreLabel());
};

Cependant, tout cela semble plutôt hacky pour simplement créer une liste de coches vertes. Cela nous amène à ...

... approche n ° 3:

Techniquement, ce n'est pas exactement ce que vous avez demandé (incrémenter le nombre d'étiquettes), mais selon votre capture d'écran, il pourrait répondre à vos besoins de manière beaucoup plus simple.

Supprimez le texte de l'étiquette existante (car elle ne doit rien afficher au démarrage) et attribuez-lui un nom unique:

<Label x:Name="ScoreLabel" FontFamily="FontAwesome" TextColor="Green"/>

Maintenant, définissez une méthode d'extension simple pour le type string qui répète une chaîne donnée un certain nombre de fois:

public static class StringExtensions
{
    public static string Repeat(this string input, int num)
    {
        return String.Concat(Enumerable.Repeat(input, num));
    }
}

(Il y a plusieurs façons de rendre cette répétition fonctionnelle aussi performante que possible, j'ai simplement choisi le type de ligne le plus simple, cherchez dans StackOverflow des discussions détaillées ...)

Vous pouvez maintenant travailler avec le contrôle Label unique défini dans XAML et lui attribuer plusieurs coches en un clic de bouton:

correctButton.Clicked += (sender, e) =>
{
    App.DB.IncrementScore();
    ScoreLabel.Text = FontAwesome.FACheck.Repeat(App.DB.Score); // replace parameter by whatever method allows you to access the current score number
};

Bien sûr, cette approche peut également être adaptée à la méthode MMVM, en utilisant simplement une propriété publique publique string au lieu de définir directement l'attribut Text de l'étiquette, mais pour cela, je vous conseillerais de jeter un coup d'œil au tutoriel MVVM du débutant.

7
andreask

Il vous suffit d'insérer un nouveau code d'étiquette dans l'événement de clic de bouton, ce qui ajoutera de nouveaux enfants à votre pile de partitions. 

cs page Code: -

button.Clicked += (sender, e) =>
    {
        App.DB.IncrementScore();
        lblStack.Children.Add(new Label {Text = FontAwesome.FACheck, TextColor = Color.Green, FontFamily = "FontAwesome"});
    };

code xamal 

<StackLayout Orientation="Horizontal" x:Name="lblStack"/>

 enter image description here

2
sumeet

Si le score est maximal, ajoutez simplement le nombre maximal d'étiquettes et associez leur visibilité.

Vous pouvez également créer une liste des étiquettes et lier la source à une collection que vous incrémentez si nécessaire.

1
François

Note: Je ne suis pas sûr si cette réponse est correcte, mais c'est trop long pour un commentaire. Juste le tester et si cela ne fonctionne pas, je vais supprimer cette réponse


Vous pouvez ajouter des contrôles par programme. N'oubliez pas que vous devez ajouter une Label à votre MainThread, car il s'agit d'une modification de l'interface utilisateur. Ajoutez ceci à votre événement Clicked:

correctButton.Clicked += (sender, e) =>
{
    App.DB.IncrementScore();
    Device.BeginInvokeOnMainThread(() => // On MainThread because it's a change in your UI
    {
        Label label = new Label();
        label.Text = "{x:Static local:FontAwesome.FACheck}"; // Not sure if this is right syntax...
        label.FontFamily = "FontAwesome";
        label.TextColor = Color.Green;
        stackPanel.Children.Add(label);
    });
};

Si vous avez une Grid, vous pouvez définir Grid.Row et Grid.Column avec la méthode SetValue d'une Control:

label.SetValue(Grid.RowProperty, 1);
label.SetValue(Grid.RowProperty, 2);
0
Dennis Schröer