Поочередно менять цвет цифр

225
03 декабря 2018, 07:40

У меня по нажатию кнопки должно менять цвет каждой цифры в Label. До этого делал 4 Label и по очереди менял их цвет но это очень крупно получается. Можно ли в моей ситуации как-ни-будь попроще или это единственный вариант? Вот как делал раньше. Тут каждый Label это своя цифра, а я бы хотел в один Label все 4 цифры. Они разделены пробелом:

Label[] labels = {label1,label2,label3,label4};
int labelsCounter = 0;
private void NextApproach_Click(object sender, RoutedEventArgs e)
{
    labels[labelsCounter].Foreground = Brushes.LightCoral;
    labelsCounter++;
    if (labelsCounter == labels.Length)
    {
        //SomeCode
    }
}
Answer 1

Вот как один из вариантов с привязками и MVVM*:

  1. Создадим базовый класс для реализации INotifyPropertyChanged

    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
  2. Создадим VM нашего числа, которая будет содержать в себе само число, цвет и простой метод для сброса цвета на стандартное:

    public class Number : BaseViewModel
    {
        public Number(int numb)
        {
            Numb = numb;
            Color = Brushes.Black;
        }
        private int numb;
        private Brush color;
        public int Numb
        {
            get => numb;
            set
            {
                numb = value;
                OnPropertyChanged();
            }
        }
        public Brush Color
        {
            get => color;
            set
            {
                color = value;
                OnPropertyChanged();
            }
        }
        public void ClearColor() => Color = Brushes.Black;
    }
  3. Далее нам нужна сама коллекция, которую мы заполним нашими цифрами:

    public ObservableCollection<Number> Numbers { get; set; } = new ObservableCollection<Number>
    {
        new Number(1),
        new Number(2),
        new Number(3),
        new Number(4)
    };
  4. Я лично размещаю эту коллекцию прям в MainWindow (но лучше все разделять на отдельные VM слои) и по этому как DataContext я укажу окно:

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
  5. Далее нам нужен функционал кнопки. Для изменения значений по очереди, нам понадобится какой нибудь счетчик, простое число. Также для удобства (что бы не вычислять позже) мы вынесем отдельно еще и предыдущее, "покрашенное" нами число:

    private int current;
    private Number prev;
  6. Теперь код самого действия:

    • Вычисляем необходимую нам цифру. Я лично сделаю это с помощью LINQ, а именно метода Skip() (который пропустит определенное число объектов) и FirstOrDefault() (который возьмет первый, подходящий нам элемент).
    • Если сохраненная нами предыдущая цифра не равна null, то выполняем сброс цвета.
    • Если наша следующая цифра не равна null (то есть найдена), меняем ей цвет и сохраняем ее для будущего изменения.
    • Ну и сам счетчик, если он меньше объектов в нашей коллекции, то прибавляем, иначе сбрасываем на ноль.

Код всего MainWindow в итоге будет следующим:

public partial class MainWindow : Window
{
    public ObservableCollection<Number> Numbers { get; set; } = new ObservableCollection<Number>
    {
        new Number(1),
        new Number(2),
        new Number(3),
        new Number(4)
    };
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
    private int current;
    private Number prev;
    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        var next = Numbers.Skip(current).FirstOrDefault();
        prev?.ClearColor();
        if (next != null)
        {
            next.Color = Brushes.Red;
            prev = next;
        }
        current = current < Numbers.Count-1 ? current + 1 : 0;
    }
}
  1. Все, осталось сделать нам XAML разметку. Она до безобразия проста:
    • StackPanel, которая позволяет нам разместить рядом контролы. В нее помещаем кнопку и ItemsControl.
    • ItemsControl - простейший вывод нашей коллекции так, как нам захочется. С помощью ItemsPanel задаем отображение элементов построчно, а с помощью ItemTemplate мы задаем вид каждого элемента.

В итоге получаем следующее:

<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <ItemsControl ItemsSource="{Binding Numbers}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Numb}" Foreground="{Binding Color}" FontSize="25"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Button Content="Сменить" Click="ButtonBase_OnClick"/>
</StackPanel>

Запускаем и любуемся результатом:

*Я не буду реализовывать тут команды и отдельный VM для основной логики. Так что это почти правильный MVVM. В реальном проекте стоит задуматься над реализацией команд, а не использовать Click!

Answer 2

Просто немного поправлю код, чтобы не переживать за значение labelsCounter

Label[] labels = {label1,label2,label3,label4};
int labelsCounter = 0;
private void NextApproach_Click(object sender, RoutedEventArgs e)
{
    labels[labelsCounter].Foreground = Brushes.LightCoral;
    labelsCounter = (labelsCounter+1) % labels.length;        
}

Теперь можно нажимать кнопку сколько хочешь, labelsCounter никогда не выйдет за рамки массива labels;

READ ALSO
Все маршруты ведут на главную

Все маршруты ведут на главную

После переноса с локалхост все мапршруты ведет на главную, даже не существующиеВ логах пусто

203
Фильтр на PHP + mySql

Фильтр на PHP + mySql

Всем добрый день! Есть таблица, база данных, и при загрузке страницы можно в коде задать параметр за каким будут выведены результаты (ORDER BY ******...

162
Парсинг сайта под vpn

Парсинг сайта под vpn

Необходимо парсить сайт, но проблема в том, что доступ к нему только при поднятом впнСкрипт будет выполняться на сервере на Debian

218
Laravel меню страниц из базы данных

Laravel меню страниц из базы данных

Хочу сделать правильноЗадумано, что можно создавать страницы на сайте через панель администратора

174