it-roy-ru.com

Добавить несколько меток в Xamarin Forms

У меня есть следующий ярлык:

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

И событие на кнопке: 

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

Это происходит каждый раз, когда я нажимаю на кнопку, моя оценка увеличивается на 1. Что я хотел сделать, так это увеличивать количество Labels в зависимости от количества оценок. Смотрите прикрепленное изображение ниже:

 enter image description here

У кого-нибудь есть идеи, как мне этого добиться? 

16
user6742877

Есть разные решения этого вопроса. Обязательно прочитайте все из них, прежде чем выбрать один - мой любимый (самый простой) указан внизу ...

Подход № 1:

Как предложили несколько человек, вы можете создать некоторый элемент управления коллекцией (я скоро к этому вернусь), определить ObservableCollection внутри ViewModel, установить Binding Context страницы для экземпляра этой ViewModel и добавить элементы в коллекцию с помощью кнопки. нажмите:

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);
};

Тип ObservableCollection на самом деле не имеет значения, поскольку мы используем одну и ту же статическую ItemTemplate для всех элементов:

<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>

Основная проблема этого подхода заключается в том, что Xamarin.Forms ListView не может отображать свои элементы по горизонтали. Это означает, что вам нужно загрузить один из доступных пакетов HorizontalListView Nuget или использовать встроенный (только в Xamarin.Forms 2.3 и выше!) CarouselView :

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

Затем, возможно, вы захотите потратить некоторое время на удаление всех визуальных эффектов для пролистывания карусели и для выбора элементов, если вы решите использовать горизонтальный ListView ...

Вместо этого есть два альтернативных решения, которые требуют меньше усилий:

Подход № 2:

Очевидно, что простой подход заключается в создании метки «шаблон» в коде:

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

... добавить горизонтальную StackLayout на страницу:

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

... и добавить новые ярлыки трудным путем:

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

Тем не менее, все это выглядит довольно просто для создания списка зеленых галочек. Это приводит нас к ...

... подход № 3:

Технически, это не совсем то, что вы просили (увеличить количество меток), но в соответствии с вашим снимком экрана это может удовлетворить ваши потребности намного проще.

Удалите существующий текст метки (так как он не должен отображать ничего при запуске), и вместо этого дайте ему уникальное имя:

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

Теперь определим простой метод расширения для типа string, который повторяет данную строку определенное количество раз:

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

(Есть несколько способов сделать эту функцию repeat максимально производительной, я просто выбрал простейшую доступную однострочную строку, для подробного обсуждения поищите в StackOverflow ...)

Теперь вы можете работать с одним элементом управления Label, определенным в XAML, и просто назначить ему несколько галочек при нажатии кнопки:

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
};

Конечно, этот подход также может быть адаптирован для использования в MMVM путем простого использования общедоступного связываемого свойства string вместо непосредственной установки атрибута метки Text, но для этого я бы посоветовал вам взглянуть на учебник MVVM для начинающих.

7
andreask

Просто вставьте новый код метки в событие нажатия кнопки, которое добавит новых детей в ваш набор очков. 

код страницы cs: -

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

хамальный код 

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

 enter image description here

2
sumeet

Если счет имеет максимум, просто добавьте максимальное количество меток и свяжите их видимость.

Или вы можете создать список меток и связать источник с коллекцией, которую вы увеличиваете при необходимости.

1
François

Примечание: я не уверен, что этот ответ правильный, но он слишком длинный для комментария. Просто проверьте это, и если это не сработает, я удалю этот ответ


Вы можете добавить элементы управления программно. Имейте в виду, что вам нужно добавить Label в свой MainThread, потому что это изменение пользовательского интерфейса. Добавьте это к вашему 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);
    });
};

Если у вас есть Grid, вы можете установить Grid.Row и Grid.Column с помощью метода SetValue для Control:

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