Table of Contents

Ваш первый экран

На этой странице мы соберём небольшое главное меню: заголовок и две кнопки, описанные разметкой и связанные с кодом игры через привязку данных. Предполагается, что вы прошли Начало работы со Stride или с MonoGame.

1. Опишите меню разметкой

Добавьте в проект игры файл Menu.xml:

<!-- Data context: an object with Title, PlayCommand and QuitCommand properties. -->
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
  <TextBlock FontSize="32" Margin="0,0,0,24" HorizontalAlignment="Center" Text="{Binding Path=Title}" />
  <Button Padding="24,8" Margin="0,0,0,8" Command="{Binding Path=PlayCommand}">Play</Button>
  <Button Padding="24,8" Command="{Binding Path=QuitCommand}">Quit</Button>
</StackPanel>

Установите для него свойство Copy to Output Directory в «Copy if newer» или добавьте в файл проекта:

<ItemGroup>
  <None Update="Menu.xml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Разметка — обычный XML: каждый элемент — это элемент управления IcyUI, а каждый атрибут задаёт свойство. Три значения {Binding Path=...} — не готовый текст: они читают Title, PlayCommand и QuitCommand из контекста данных меню — объекта, который вы передаёте из кода.

2. Загрузите её и передайте данные

Замените стартовый скрипт этим (и выберите MenuStartup в Add component):

using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Icy.Stride.Configuration;
using Stride.Engine;

/// <summary>
/// The menu's data: what the markup's {Binding} expressions read. ObservableObject raises PropertyChanged, so the
/// screen updates when Title changes.
/// </summary>
public sealed class MenuViewModel : ObservableObject
{
    private string title = "My Game";

    public string Title
    {
        get => title;
        set => SetProperty(ref title, value);
    }

    public ICommand PlayCommand { get; } = new RelayCommand(() => { /* Start the game. */ });

    public ICommand QuitCommand { get; } = new RelayCommand(() => { /* Exit. */ });
}

/// <summary>Replaces IcyUIStartup: loads Menu.xml (copied to the output folder) onto the main canvas.</summary>
public class MenuStartup : StartupScript
{
    public override void Start() =>
        Game.UseIcyUI().MainCanvas.LoadMarkup("Menu.xml", new MenuViewModel());
}

LoadMarkup(string, object?) загружает файл разметки из папки сборки игры, делает модель представления DataContext меню, чтобы каждая {Binding} внутри читала данные из неё, и добавляет меню на Canvas. Щелчок по кнопке или её активация с клавиатуры или геймпада выполняет её команду.

Что получилось

Меню, у которого компоновка живёт в разметке, а поведение — в C#. Меняйте разметку, чтобы переоформить или перестроить меню, не трогая код. MenuViewModel наследует ObservableObject (из CommunityToolkit.Mvvm, от которого IcyUI уже зависит), поэтому изменение его Title во время игры обновляет заголовок на экране. Модель представления, которая не вызывает PropertyChanged, читается только один раз — при создании привязки.

Далее