2017-01-14 4 views
16

У меня есть следующие метки:Добавление нескольких меток в Xamarin Forms

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

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

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

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

enter image description here

Любые имеет какие-либо идеи, как я могу добиться этого?

+2

Я настоятельно рекомендую посмотреть в архитектуру MVVM для этого приложения. Вы можете привязать свои метки к 'ObservableCollection ' в вашем ViewMidel. –

+1

@RobLyndon благодарит.Я знаю о MVVM, но я не знаю, как его применять здесь. Можете ли вы дать мне образец кода, относящийся к моей проблеме? –

ответ

7

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

Подход № 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 ac tually не имеет значения, так как мы используем один и тот же статический 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 там, или использовать built-in (only in Xamarin.Forms 2.3 and above!) 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()); 
}; 

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

... Подход # 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)); 
    } 
} 

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

Теперь вы можете работать с одним 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, просто используя общедоступное свойство bindable string вместо установки атрибута метки Text непосредственно, но для этого я бы посоветовал вам взглянуть на учебник MVVM для начинающих.

+0

спасибо. Я пытаюсь использовать подход №3, но im получить ошибку 'string не был признан как допустимый логический'. Любая идея почему? –

+0

На какой строке это ошибка? Кроме того, можете ли вы показать точное нажатие кнопки мыши после его адаптации в соответствии с вашими потребностями? – andreask

+1

Извините, его ошибка. Я добавил свойство IsVisible в свой ярлык, пока я раньше занимался кодом, но оставил значение пустым. Я буду работать над кодом больше с вашим решением, а затем сообщит вам, когда это будет работать. –

1

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

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

+0

Я мог бы сделать это, но это не очень чистое решение, так как у меня максимальное количество 20 баллов. –

+0

Я обновился, чтобы предложить другую идею. –

0

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


Вы можете добавить элементы управления программно. Имейте в виду, что вам нужно добавить 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); 
1

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

CS страница Код: -

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

код xamal

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

enter image description here

+0

это выглядит простое решение .. –