как создать 25 кнопок не прописывая их в xaml в ручную и не нарушив подход mvvm c# wpf

сейчас кнопки создаются так но мне за это хотят сломать ноги

public ObservableCollection<Button> Buttons { get; private set; }   

 ObservableCollection<Button> CreateButtons(ObservableCollection<Button> but)
        {
            but = new ObservableCollection<Button>();
            for (int i = 0 ; i < 25; i++)
            {
                btn[i] = new Button();
                btn[i].CommandParameter = i;
                btn[i].Background = Brushes.Blue;
                btn[i].Command = ColorChange;
                btn[i].BorderBrush= new SolidColorBrush(Colors.Black);
                but.Add(btn[i]);
            }
            return but;
        }
  public SlotMineViewModel()//конструктор
        {
            Buttons = CreateButtons(Buttons);
        }

xaml

<ItemsControl Grid.Column="0" Grid.ColumnSpan="5" ItemsSource="{Binding Buttons}">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <UniformGrid Rows="5" Columns="5" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                               <Button Content="{Binding Text}" Command="{BindingCommand}"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>

Ответы (1 шт):

Автор решения: OwDafuq

ViewModel не должна управлять кнопками уж точно (их созданием как минимум).

За это должен отвечать View слой. У вас мысль правильная: использовать ItemsControl, но только почему-то вы решили, что в ObservableCollection нужно складывать сами кнопки, что не верно.

Допустим, что у нас есть ViewModel:

class ViewModel
{
    public ObservableCollection<string> Buttons { get; }

    public ViewModel()
    {
        Buttons = new ObservableCollection<string>();

        foreach (var button in Enumerable.Range(0, 10))
        {
            Buttons.Add($"Button #{button + 1}");
        }
    }
}

В ObservableCollection у нас будут лежать только какие-то "бизнес" данные, в текущем примере - только названия кнопок.

Далее во View слое мы делаем биндинг на эту коллекцию и создаем кнопки:

<ItemsControl ItemsSource="{Binding Buttons}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Обратите внимание, что Content="{Binding}" сделано т.к. в элементе коллекции только строка, а не объект, к которому можно было бы обратиться по имени свойства.

Таким образом мы получаем на форме 10 кнопок:

10 кнопок на форме

UPD: пример с использованием какой-то бизнес сущности в ObservableCollection

BusinessButtonData:

class BusinessButtonData
{
    public Guid Guid { get; set; }
    public string Name { get; set; }
}

ViewModel:

class ViewModel
{
    public ObservableCollection<BusinessButtonData> Buttons { get; }

    public ViewModel()
    {
        Buttons = new ObservableCollection<BusinessButtonData>();

        foreach (var button in Enumerable.Range(0, 10))
        {
            Buttons.Add(new BusinessButtonData { Guid = Guid.NewGuid(), Name = $"Button #{button + 1}" });
        }

        ButtonCommand = new DelegateCommand<BusinessButtonData>(ButtonClick); //где DelegateCommand - ваша реализация команды
    }

    public ICommand ButtonCommand { get; set; }

    private void ButtonClick(BusinessButtonData buttonData)
    {
        MessageBox.Show($"Вы нажали кнопку: {buttonData.Name} с GUID = {buttonData.Guid}");
    }
}

И итоговая View:

<ItemsControl ItemsSource="{Binding Buttons}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding Name}"
                    Command="{Binding DataContext.ButtonCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                    CommandParameter="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
→ Ссылка