Suppose I have an array of strings [3,3] and a UniformGrid within which there are 9 pieces. Label. How to bind each element of the array to a specific Label? Or create a property for each element and bind to each Label?

<UniformGrid Rows="3" Columns="3" x:Name="myGrid"}" <Label></Label> <Label></Label> <Label></Label> <Label></Label> <Label></Label> <Label></Label> <Label></Label> <Label></Label> <Label></Label> </UniformGrid> 

    1 answer 1

    Very simple!

    Here is an example.

    1. Xaml The idea here is that for a Binding you need an ItemsControl for the list of items. And for its location as in the UniformGrid you need to override the ItemsPanel :

       <Window x:Class="SO8WPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SO8WPF" Title="Binding to uniform grid" Height="350" Width="525"> <ItemsControl ItemsSource="{Binding Items}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <UniformGrid Columns="3" Rows="3" IsItemsHost="True"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Label Content="{Binding Text}"> <Label.Background> <SolidColorBrush Color="{Binding Color}"/> </Label.Background> </Label> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Window> 
    2. Now view model. We take the standard implementation of INPC, nothing special.

       public class ItemVM : INotifyPropertyChanged { string text; public string Text { get { return text; } set { if (text != value) { text = value; NotifyPropertyChanged(); } } } Color color; public Color Color { get { return color; } set { if (color != value) { color = value; NotifyPropertyChanged(); } } } void NotifyPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; } 
    3. We put VM in the flat list. If indexing with two indexes is really necessary, we do it separately.

       class MainVM { public ObservableCollection<ItemVM> Items { get; } = new ObservableCollection<ItemVM>() { new ItemVM() { Text = "Fünf", Color = Colors.Chocolate }, new ItemVM() { Text = "Sechs", Color = Colors.DarkSlateBlue }, new ItemVM() { Text = "Alte", Color = Colors.Maroon }, new ItemVM() { Text = "Hex", Color = Colors.LawnGreen }, new ItemVM() { Text = "Sieben", Color = Colors.DeepPink }, new ItemVM() { Text = "Acht", Color = Colors.Turquoise }, new ItemVM() { Text = "Gute", Color = Colors.Silver }, new ItemVM() { Text = "Nacht", Color = Colors.Orange } }; public ItemVM this[int i, int j] { get { return Items[i * 3 + j]; } set { Items[i * 3 + j] = value; } } } 
    4. App.xaml empty, we first equip the window with VM, and only show it later:

       <Application x:Class="SO8WPF.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> </Application> 
       public partial class App : Application { MainVM mainVM = new MainVM(); protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); new MainWindow() { DataContext = mainVM }.Show(); } } 

    Voila! We got this picture:

    Uniform grid


    For the case when something should happen to the object by clicking, commands are used. Let's make it so that when clicked, the object is repainted in a random color.

    First, we need a team, that is, the implementation of ICommand . I am implementing the simplest option, but you may need something more intelligent. With SimpleCommand you can bind a command to your lambda or method.

     class SimpleCommand : ICommand { private readonly Action onCommand; public SimpleCommand(Action onCommand) { this.onCommand = onCommand; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return true; } public void Execute(object parameter) { onCommand(); } } 

    Next, add the ItemVM command and its implementation:

     public class ItemVM : INotifyPropertyChanged { // добавили общий генератор случайных чисел static Random rnd = new Random(); public ItemVM() { // привязываем команду к методу OnActivation Activate = new SimpleCommand(OnActivation); } string text; public string Text { get { return text; } set { if (text != value) { text = value; NotifyPropertyChanged(); } } } Color color; public Color Color { get { return color; } set { if (color != value) { color = value; NotifyPropertyChanged(); } } } // добавили свойство с командой, которая устанавливается в конструкторе public ICommand Activate { get; } void NotifyPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } void OnActivation() { // меняем цвет на случайный Color = Color.FromRgb( (byte)rnd.Next(256), (byte)rnd.Next(256), (byte)rnd.Next(256)); } public event PropertyChangedEventHandler PropertyChanged; } 

    OK, the VM part is fine. Now you need to fasten the command to the click. It is done this way.

    First, you need to connect the System.Windows.Interactivity.WPF nuget package (as usual, right-click on References → Manage NuGet Packages ...). Having this, we modify our template for the element:

     <Label Content="{Binding Text}"> <!-- привязываем команду Activate к событию MouseLeftButtonUp --> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseLeftButtonUp"> <i:InvokeCommandAction Command="{Binding Activate}"/> </i:EventTrigger> </i:Interaction.Triggers> <Label.Background> <SolidColorBrush Color="{Binding Color}"/> </Label.Background> </Label> 

    Do not forget to add to the list of namespace windows

     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 

    Shouting a bit, we get a repainted picture:

    Repainted!

    • one
      Yeah, and now the cell number is easy to fasten. I told you :). - andreycha
    • @VladD, good example, thanks! - Lightness
    • one
      @andreycha, spoke, and now I will try to fasten) - Lightness
    • @Lightness good luck). - andreycha
    • @Lightness: Please! - VladD