At the press of a button, I should change the color of each digit in Label . Before that I did 4 Label and in turn changed their color but it turns out very large. Is it possible in my situation to be somehow simpler or is this the only option? That's how I did before. Here each Label is its own digit, and I would like in one Label all 4 digits. They are separated by a space:

 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 } } 
  • What are the numbers? For what? It is impossible to add a color to the model model and add labels to it? Then just change the color in the model and voila - tym32167
  • If you have numbers, this is your own separate object and their number changes, then create a collection that will contain the VM of this object (name, color, action, etc.) and output them as a collection through the same ItemsControl or its analog ... If you have static numbers, make a TextBlock , which will contain inside Run with its text and color. - EvgeniyZ
  • I always have 4 digits, but it can be in the range from 0 to 100. If you can show an example of code. - Aqua
  • Then the easiest option ... - EvgeniyZ
  • and changing the value can be banned? - Aqua

2 answers 2

Here's how one of the options with bindings and MVVM *:

  1. Create a base class for implementing INotifyPropertyChanged

     public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } 
  2. Create a VM of our number, which will contain the number, color and a simple method to reset the color to the standard one:

     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. Next we need the collection itself, which we fill with our numbers:

     public ObservableCollection<Number> Numbers { get; set; } = new ObservableCollection<Number> { new Number(1), new Number(2), new Number(3), new Number(4) }; 
  4. I personally place this collection straight into MainWindow (but it’s better to split everything into separate VM layers) and for that, as a DataContext I’ll point to the window:

     public MainWindow() { InitializeComponent(); DataContext = this; } 
  5. Next, we need the functionality of the button. To change the values ​​in turn, we need some sort of counter, a prime number. Also for convenience (that would not calculate later) we will carry out separately the previous one, the "colored" number:

     private int current; private Number prev; 
  6. Now the code of the action itself:

    • We calculate the number we need. I personally will do this using LINQ, namely the Skip() method (which will skip a certain number of objects) and FirstOrDefault() (which will take the first element that FirstOrDefault() us).
    • If the previous digit that we saved is not null , then reset the color.
    • If our next digit is not null (that is, it is found), change its color and save it for future change.
    • Well, the counter itself, if it is less than the objects in our collection, then add, otherwise reset to zero.

The code for the whole MainWindow will be as follows:

 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. All that's left is to make us XAML markup. It is outrageously simple:
    • StackPanel , which allows us to place controls nearby. In it we place the button and ItemsControl .
    • ItemsControl - the simplest conclusion of our collection as we like. Using ItemsPanel set the display of items line by line, and with the help of an ItemTemplate we set the look of each item.

As a result, we obtain the following:

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

Run and admire the result:

Result

* I will not implement commands and a separate VM for the main logic here. So this is almost the right MVVM. In a real project, you should think about the implementation of commands, and not to use Click !

    Just correct the code a bit so as not to worry about the value of 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; } 

    Now you can press the button as you want, labelsCounter will never go beyond the array of labels ;