Для кого ориентирован данный гайд?
Допустим, вы уже прочитали все доступные документации по программированию Space Station 14, но всё ещё не понимаете, как именно что-то должно работать. Этот гайд для новичков, которые хотят научиться создавать пользовательские интерфейсы (UI) для SS14.
Вводная
Представьте ситуацию: вы прочитали ВСЕ документации по SS14. Все.
Вы знаете, что такое Entity, Component, System... Но когда дело доходит до создания окошка с кнопочкой - вы не понимаете что это такое.
Спокойно! Этот гайд - поможет базово ознакомиться с UI в разработке SS14. Посмотрим как можно сделать: окна, кнопки, которые реально работают, и интерфейсы, от которых игроки не будут в ужасе закрывать игру ахаха.
Архитектура Content & Engine
SS14 есть слои в сборках. Вот краткое пояснение:
RobustToolbox (Engine) - "Фундамент"
Это база. Тут живут скучные, но важные вещи:
- 1 - Математика и физика (да, без них никуда, как бы нам этого ни хотелось)
- 2 - Рендер графики (чтобы вы видели свои творения, а не чёрный экран)
- 3 - Сетевое взаимодействие (чтобы игроки могли друг друга бить кувалдами)
- 4 - Система UI (включая XAML, XML, CSS)
Content (Контент)
В сборке вы увидите папки Content - это ваша песочница:
- Content.Client - тут живут ваши окна, кнопочки и прочий UI. Ваш второй дом.
- Content.Server - тут живёт логика сервера. Он решает, кто жил, а кто умер.
- Content.Shared - общий код. Швейцарский нож: и клиент, и сервер могут им пользоваться.
Важный инсайт: 99% времени вы будете ковыряться в Content. Это нормально.
Система UI: XAML + Code-behind
UI в SS14 использует XAML - язык разметки на основе XML для описания структуры интерфейсов.
XAML позволяет описывать деревья контролов в декларативном стиле.
Каждое изменение требует перекомпиляции - горячая перезагрузка не поддерживается.
Что такое XAML?
XAML (eXtensible Application Markup Language) - это язык разметки, но который выглядит как XML и... (ладно, это и есть XML)
С его помощью вы описываете:
- - Кнопки (чтобы игроки могли на них тыкать)
- - Текстовые поля (чтобы игроки могли писать там глупости ехех)
- - Панели (чтобы всё это не развалилось)
- - Списки (потому что все любят списки)
- - И вообще всё, что можно увидеть глазами
Что такое Code-behind?
Code-behind - это ваш C# класс, который дружит с XAML файлом. Он:
- - Слушает, что делает пользователь (нажал кнопку? Получи реакцию!)
- - Обновляет данные в UI (чтобы игроки видели актуальную информацию)
- - Общается с сервером (потому что без сервера мы никто)
Структура UI файла
Каждый UI компонент в SS14 состоит из двух файлов:
MyWindow.xaml # Разметка UI (структура, элементы)
MyWindow.xaml.cs # Логика UI (обработчики событий, связь с данными)
Пример простой структуры
MyWindow.xaml:
<DefaultWindow xmlns="https://spacestation14.io"
Title="Моё окно"
MinSize="300 200">
<BoxContainer Orientation="Vertical">
<Label Text="Привет, мир!" />
<Button Name="MyButton" Text="Нажми меня" />
</BoxContainer>
</DefaultWindow>
MyWindow.xaml.cs:
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.MyModule.UI;
[GenerateTypedNameReferences]
public sealed partial class MyWindow : DefaultWindow
{
public MyWindow()
{
RobustXamlLoader.Load(this);
// Подписываемся на событие нажатия кнопки
MyButton.OnPressed += _ =>
{
// Действие при нажатии
};
}
}
Базовые элементы управления (Controls)
1. Контейнеры (Containers)
Контейнеры используются для группировки и расположения элементов.
BoxContainer - универсальный контейнер
<!-- Вертикальное расположение (элементы сверху вниз) -->
<BoxContainer Orientation="Vertical">
<Label Text="Первый" />
<Label Text="Второй" />
<Label Text="Третий" />
</BoxContainer>
<!-- Горизонтальное расположение (элементы слева направо) -->
<BoxContainer Orientation="Horizontal">
<Label Text="Левый" />
<Label Text="Правый" />
</BoxContainer>
Важные свойства BoxContainer:
Orientation="Vertical"- вертикальное расположениеOrientation="Horizontal"- горизонтальное расположениеSeparationOverride="10"- отступ между элементами в пикселяхMargin="10 5"- внешний отступ (горизонтальный вертикальный)
ScrollContainer - контейнер с прокруткой
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
<BoxContainer Name="ContentList" Orientation="Vertical">
<!-- Много элементов, которые можно прокручивать -->
</BoxContainer>
</ScrollContainer>
GridContainer - сетка
<GridContainer Columns="3">
<Label Text="1,1" />
<Label Text="1,2" />
<Label Text="1,3" />
<Label Text="2,1" />
<Label Text="2,2" />
<Label Text="2,3" />
</GridContainer>
PanelContainer - контейнер с фоном
<PanelContainer StyleClasses="BackgroundPanel">
<Label Text="Текст на фоне" />
</PanelContainer>
2. Текстовые элементы
Label - простая надпись
<!-- Простой текст -->
<Label Text="Привет, мир!" />
<!-- С локализацией -->
<Label Text="{Loc 'my-window-title'}" />
<!-- С выравниванием -->
<Label Text="По центру" HorizontalAlignment="Center" />
<!-- Со стилем -->
<Label Text="Заголовок" StyleClasses="LabelHeading" />
<!-- С ограничением ширины и переносом текста -->
<Label Text="Длинный текст..." SetWidth="200" />
Часто используемые стили Label:
LabelHeading- заголовокLabelSubText- подзаголовок (мелкий текст)LabelBig- большой текстLabelKeyText- текст для клавиш
RichTextLabel - текст с форматированием
<RichTextLabel Name="Description" SetWidth="300" />
В C# коде можно установить форматированный текст:
Description.SetMessage(FormattedMessage.FromMarkup
("Текст с [color=red]красным[/color] словом"));
3. Кнопки
Button - обычная кнопка
<!-- Простая кнопка -->
<Button Text="Нажать" />
<!-- Кнопка с Name для доступа в коде -->
<Button Name="ConfirmButton" Text="Подтвердить" />
<!-- Кнопка-переключатель -->
<Button Name="ToggleLight" Text="Свет" ToggleMode="True" />
<!-- Кнопка с иконкой -->
<Button Name="IconButton">
<TextureRect TexturePath="/Textures/Interface/Icons/plus.png" />
</Button>
<!-- Кнопка во всю ширину -->
<Button Name="WideButton" Text="Широкая" HorizontalExpand="True" />
Стили кнопок:
ButtonSquare- квадратная кнопкаOpenLeft- открыта слева (для группы кнопок)OpenRight- открыта справаOpenBoth- открыта с обеих сторонButtonCaution- красная кнопка (опасность)
<Button Text="Опасно" StyleClasses="ButtonCaution" />
TextureButton - кнопка с текстурой
<TextureButton Name="CloseButton"
StyleClasses="windowCloseButton"
VerticalAlignment="Center" />
CheckBox - флажок
<CheckBox Name="EnableSound" Text="Включить звук" />
4. Поля ввода
LineEdit - однострочное поле ввода
<!-- Простое поле -->
<LineEdit Name="NameInput" />
<!-- С плейсхолдером -->
<LineEdit Name="SearchBar" PlaceHolder="Поиск..." />
<!-- С начальным текстом -->
<LineEdit Name="NameEdit" Text="Имя" />
<!-- Во всю ширину -->
<LineEdit Name="WideInput" HorizontalExpand="True" />
SpinBox - ввод чисел
<SpinBox Name="AmountInput" Value="1" MinWidth="100" />
FloatSpinBox - ввод дробных чисел
<FloatSpinBox Name="RatioInput" Value="1.0" MinWidth="80" />
5. Выбор из списка
OptionButton - выпадающий список
<OptionButton Name="CategorySelector" HorizontalExpand="True" />
В C# коде:
// Добавление вариантов
CategorySelector.AddItem("Вариант 1", 1);
CategorySelector.AddItem("Вариант 2", 2);
// Получение выбранного
var selectedId = CategorySelector.SelectedId;
ItemList - список элементов
<ScrollContainer VerticalExpand="True">
<ItemList Name="ItemsList" VerticalExpand="True" />
</ScrollContainer>
6. Прогресс и индикаторы
ProgressBar - полоса прогресса
<ProgressBar Name="HealthBar"
MinValue="0"
MaxValue="100"
Value="75"
HorizontalExpand="True" />
7. Изображения
TextureRect - изображение
<TextureRect TexturePath="/Textures/Interface/Icons/star.png"
Stretch="KeepAspectCentered"
SetSize="32 32" />
SpriteView - просмотр спрайта сущности
<SpriteView Name="EntityPreview"
OverrideDirection="South"
Scale="2 2"
SetSize="64 64" />
Окна (Windows)
DefaultWindow - базовое окно
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'my-window-title'}"
MinSize="400 300"
SetSize="400 300"
Resizable="True">
<BoxContainer Orientation="Vertical" Margin="10">
<!-- Содержимое окна -->
</BoxContainer>
</DefaultWindow>
FancyWindow - улучшенное окно
FancyWindow имеет дополнительные возможности:
- Кнопка справки
- Лучший заголовок
- Возможность прикрепить гайдбук
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls=
"clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'my-fancy-window-title'}"
MinSize="500 400"
Resizable="True">
<BoxContainer Orientation="Vertical" Margin="10">
<!-- Содержимое окна -->
</BoxContainer>
</controls:FancyWindow>
Свойства элементов
Размеры
<!-- Минимальный размер -->
<Label MinSize="100 30" />
<!-- Точный размер -->
<Label SetSize="200 50" />
<!-- Максимальный размер -->
<Label MaxSize="300 100" />
Расширение
Важно: HorizontalExpand и VerticalExpand работают только в контейнерах BoxContainer, SplitContainer и GridContainer. В других контейнерах эти свойства игнорируются.
<!-- Расширяться по горизонтали -->
<Button HorizontalExpand="True" />
<!-- Расширяться по вертикали -->
<BoxContainer VerticalExpand="True" />
<!-- Расширяться в обе стороны -->
<PanelContainer HorizontalExpand="True" VerticalExpand="True" />
Пропорциональное распределение места:
Если несколько элементов имеют Expand="True", пространство распределяется пропорционально их SizeFlagsStretchRatio:
<!-- Первый элемент получит в 2 раза больше места -->
<Button VerticalExpand="True" SizeFlagsStretchRatio="2" Text="Большой" />
<Button VerticalExpand="True" SizeFlagsStretchRatio="1" Text="Маленький" />
Выравнивание
HorizontalAlignment и VerticalAlignment определяют, как элемент располагается внутри выделенного ему пространства. По умолчанию оба значения Stretch (растягивание).
<!-- Горизонтальное выравнивание -->
<Label HorizontalAlignment="Center" /> <!-- Центр -->
<Label HorizontalAlignment="Left" /> <!-- Влево -->
<Label HorizontalAlignment="Right" /> <!-- Вправо -->
<Label HorizontalAlignment="Stretch" /> <!-- Растянуть (по умолчанию) -->
<!-- Вертикальное выравнивание -->
<Label VerticalAlignment="Center" /> <!-- Центр -->
<Label VerticalAlignment="Top" /> <!-- Вверх -->
<Label VerticalAlignment="Bottom" /> <!-- Вниз -->
<Label VerticalAlignment="Stretch" /> <!-- Растянуть (по умолчанию) -->
Важно понимать разницу:
Alignment— как элемент ведёт себя внутри уже выделенного пространстваExpand— сколько пространства родительский контейнер выделит элементу
Отступы
<!-- Внешний отступ (все стороны одинаковые) -->
<BoxContainer Margin="10" />
<!-- Внешний отступ (горизонтальный вертикальный) -->
<BoxContainer Margin="10 5" />
<!-- Внешний отступ (левый верхний правый нижний) -->
<BoxContainer Margin="5 10 5 10" />
Name и доступ к элементам
Атрибут Name
Атрибут Name позволяет обращаться к элементу из C# кода:
<Button Name="ConfirmButton" Text="Подтвердить" />
<Label Name="StatusLabel" Text="Статус" />
<LineEdit Name="NameInput" PlaceHolder="Введите имя" />
Атрибут Access
Access определяет уровень доступа к элементу:
<!-- Публичный доступ (можно использовать из других классов) -->
<Button Name="PublicButton" Access="Public" />
<!-- Внутренний доступ (только внутри сборки) -->
<Button Name="InternalButton" Access="Internal" />
<!-- Приватный доступ (только в этом классе) -->
<Button Name="PrivateButton" Access="Private" />
Связь XAML и C# кода
GenerateTypedNameReferences
Атрибут [GenerateTypedNameReferences] автоматически генерирует ссылки на элементы с Name:
[GenerateTypedNameReferences]
public sealed partial class MyWindow : DefaultWindow
{
public MyWindow()
{
RobustXamlLoader.Load(this);
// ConfirmButton автоматически доступен!
ConfirmButton.Text = "Нажми меня";
ConfirmButton.OnPressed += OnConfirmPressed;
}
private void OnConfirmPressed(BaseButton.ButtonEventArgs args)
{
// Действие при нажатии
}
}
Внедрение зависимостей
Для IoC сервисов и других контроллеров используйте [Dependency]:
[GenerateTypedNameReferences]
public sealed partial class MyWindow : DefaultWindow
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
public MyWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
// Теперь можно использовать _entityManager и _prototype
}
}
Важно: Для entity systems в UI контроллерах используйте [UISystemDependency] вместо [Dependency].
События и обработчики
События кнопок
// Одинарное нажатие
MyButton.OnPressed += _ => { /* действие */ };
// Нажатие и отпускание
MyButton.OnMouseDown += _ => { /* нажата */ };
MyButton.OnMouseUp += _ => { /* отпущена */ };
// Режим переключателя (ToggleMode="True")
MyToggleButton.OnToggled += args =>
{
if (args.Pressed)
{
// Включено
}
else
{
// Выключено
}
};
События LineEdit
// При изменении текста
MyInput.OnTextChanged += args =>
{
var text = args.Text;
};
// При нажатии Enter
MyInput.OnTextEntered += args =>
{
var text = args.Text;
};
// При получении/потере фокуса
MyInput.OnFocusEnter += _ => { /* фокус получен */ };
MyInput.OnFocusExit += _ => { /* фокус потерян */ };
События CheckBox
MyCheckBox.OnToggled += args =>
{
var isChecked = args.Pressed;
};
Локализация в UI
Использование {Loc}
<!-- Текст с локализацией -->
<Label Text="{Loc 'my-window-title'}" />
<!-- Кнопка с локализацией -->
<Button Text="{Loc 'my-button-text'}" />
<!-- ToolTip с локализацией -->
<Button Text="?" ToolTip="{Loc 'help-tooltip'}" />
Файлы локализации
Создайте FTL файл в /Resources/Locale/en-US/my-module.ftl:
my-window-title = Моё окно
my-button-text = Нажать
help-tooltip = Это подсказка
Полный пример: Окно настроек
SettingsWindow.xaml
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'settings-window-title'}"
MinSize="400 350"
Resizable="False">
<BoxContainer Orientation="Vertical" Margin="10" SeparationOverride="8">
<!-- Заголовок -->
<Label Text="{Loc 'settings-general'}" StyleClasses="LabelHeading" />
<!-- Настройка звука -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'settings-sound-volume'}" MinWidth="120" />
<ProgressBar Name="VolumeBar"
MinValue="0" MaxValue="100" Value="50"
HorizontalExpand="True" />
</BoxContainer>
<!-- Чекбоксы -->
<CheckBox Name="EnableMusicCheckBox" Text="{Loc 'settings-enable-music'}"/>
<CheckBox Name="EnableSfxCheckBox" Text="{Loc 'settings-enable-sfx'}"
Pressed="True" />
<!-- Разделитель -->
<PanelContainer StyleClasses="LowDivider" />
<!-- Поле ввода имени -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'settings-player-name'}" MinWidth="120" />
<LineEdit Name="PlayerNameInput" HorizontalExpand="True"
PlaceHolder="{Loc 'settings-name-placeholder'}" />
</BoxContainer>
<!-- Выбор темы -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'settings-theme'}" MinWidth="120" />
<OptionButton Name="ThemeSelector" HorizontalExpand="True" />
</BoxContainer>
<!-- Разделитель -->
<PanelContainer StyleClasses="LowDivider" />
<!-- Кнопки -->
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Right">
<Button Name="ResetButton" Text="{Loc 'settings-reset'}"
StyleClasses="ButtonSquare" />
<Control MinWidth="10" />
<Button Name="SaveButton" Text="{Loc 'settings-save'}"
StyleClasses="ButtonSquare" />
</BoxContainer>
</BoxContainer>
</DefaultWindow>
SettingsWindow.xaml.cs
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.MyModule.UI;
[GenerateTypedNameReferences]
public sealed partial class SettingsWindow : DefaultWindow
{
public SettingsWindow()
{
RobustXamlLoader.Load(this);
// Инициализация выпадающего списка
ThemeSelector.AddItem("Тёмная", 0);
ThemeSelector.AddItem("Светлая", 1);
ThemeSelector.AddItem("Системная", 2);
ThemeSelector.SelectId(0);
// Подписка на события
SaveButton.OnPressed += OnSavePressed;
ResetButton.OnPressed += OnResetPressed;
}
private void OnSavePressed(BaseButton.ButtonEventArgs args)
{
// Сохранение настроек
var playerName = PlayerNameInput.Text;
var enableMusic = EnableMusicCheckBox.Pressed;
var enableSfx = EnableSfxCheckBox.Pressed;
var volume = VolumeBar.Value;
var theme = ThemeSelector.SelectedId;
// ... логика сохранения ...
Close();
}
private void OnResetPressed(BaseButton.ButtonEventArgs args)
{
// Сброс к значениям по умолчанию
PlayerNameInput.Text = "";
EnableMusicCheckBox.Pressed = false;
EnableSfxCheckBox.Pressed = true;
VolumeBar.Value = 50;
ThemeSelector.SelectId(0);
}
}
Связь с сервером (Network Messages)
Для создания интерактивного UI, которое взаимодействует с сервером, нужно:
1. Создать сетевые сообщения
Shared/MyWindowMessages.cs:
using Robust.Shared.Serialization;
namespace Content.Shared.MyModule;
[Serializable, NetSerializable]
public sealed class MyWindowRequestMessage : EntityEventArgs
{
public string Data { get; }
public MyWindowRequestMessage(string data)
{
Data = data;
}
}
[Serializable, NetSerializable]
public sealed class MyWindowResponseMessage : EntityEventArgs
{
public string Result { get; }
public MyWindowResponseMessage(string result)
{
Result = result;
}
}
2. Создать UI контроллер на клиенте
Client/MyWindowUIController.cs:
UI контроллеры отвечают за создание, обновление и удаление контролов. Entity systems не должны делать это напрямую.
using Content.Shared.MyModule;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controllers;
namespace Content.Client.MyModule.UI;
// IOnSystemChanged позволяет реагировать на загрузку/выгрузку системы
public sealed class MyWindowUIController : UIController, IOnSystemChanged<MyWindowSystem>
{
// Для IoC сервисов и других контроллеров используйте [Dependency]
[Dependency] private readonly IEntityManager _entityManager = default!;
// Для entity systems используйте [UISystemDependency]
[UISystemDependency] private readonly MyWindowSystem? _system = default!;
private MyWindow? _window;
public void OpenWindow()
{
if (_window == null)
{
_window = new MyWindow();
_window.OnClose += () => _window = null;
// Подписываемся на событие кнопки
_window.ConfirmButton.OnPressed += OnConfirmPressed;
}
_window.Open();
}
private void OnConfirmPressed(BaseButton.ButtonEventArgs args)
{
if (_window == null) return;
var data = _window.DataInput.Text;
// Отправляем сообщение на сервер
RaiseNetworkEvent(new MyWindowRequestMessage(data));
}
public void UpdateResponse(string result)
{
_window?.ResultLabel.Text = result;
}
// Вызывается при загрузке системы
public void OnSystemLoaded(MyWindowSystem system)
{
// Подписываемся на события системы
}
// Вызывается при выгрузке системы
public void OnSystemUnloaded(MyWindowSystem system)
{
// Отписываемся от событий
}
}
Доступные интерфейсы для UI контроллеров:
IOnSystemLoaded<T>- вызывается при загрузке системыIOnSystemUnloaded<T>- вызывается при выгрузке системыIOnStateEntered<T>- вызывается при входе в состояние (например, GameplayState)IOnStateExited<T>- вызывается при выходе из состояния
3. Создать систему на сервере
Server/MyWindowSystem.cs:
using Content.Shared.MyModule;
using Robust.Server.GameObjects;
namespace Content.Server.MyModule;
public sealed class MyWindowSystem : EntitySystem
{
public override void Initialize()
{
SubscribeNetworkEvent(OnRequest);
}
private void OnRequest(MyWindowRequestMessage msg, EntitySessionEventArgs args)
{
var sender = args.SenderSession;
// Обрабатываем запрос
var result = $"Обработано: {msg.Data}";
// Отправляем ответ клиенту
RaiseNetworkEvent(new MyWindowResponseMessage(result),
sender.ConnectedClient);
}
}
Стилизация (StyleClasses)
Применение стилей
<!-- Кнопка с классом стиля -->
<Button Text="Опасно" StyleClasses="ButtonCaution" />
<!-- Несколько классов стилей -->
<Label Text="Заголовок" StyleClasses="LabelHeading LabelBig" />
Часто используемые стили
| Элемент | Стиль | Описание |
|---|---|---|
| Button | ButtonSquare | Квадратная кнопка |
| Button | ButtonCaution | Красная кнопка опасности |
| Button | OpenLeft | Открыта слева |
| Button | OpenRight | Открыта справа |
| Button | OpenBoth | Открыта с обеих сторон |
| Label | LabelHeading | Заголовок |
| Label | LabelSubText | Мелкий текст |
| Label | LabelBig | Большой текст |
| Panel | BackgroundPanel | Фон панели |
| Panel | LowDivider | Тонкий разделитель |
| Panel | HighDivider | Толстый разделитель |
Практические советы
1. Отступы и размеры
<!-- Используйте Margin для отступов -->
<BoxContainer Margin="10">
<!-- Содержимое с отступами 10px -->
</BoxContainer>
<!-- Используйте MinSize для минимальных размеров -->
<Button MinSize="100 30" Text="Кнопка" />
<!-- Используйте HorizontalExpand/VerticalExpand для заполнения -->
<ScrollContainer VerticalExpand="True" HorizontalExpand="True">
<!-- Заполняет всё доступное пространство -->
</ScrollContainer>
2. Динамическое добавление элементов
// Добавление элемента в контейнер
var button = new Button { Text = "Динамическая кнопка" };
MyContainer.AddChild(button);
// Очистка контейнера
MyContainer.DisposeAllChildren();
3. Показ/скрытие элементов
// Скрыть элемент
MyElement.Visible = false;
// Показать элементы
MyElement.Visible = true;
4. Отладка UI
Используйте интегрированные инструменты отладки:
devwindow- открывает окно разработчика с вкладкой UI для просмотра структуры интерфейса/uitest [название_UI_окна]- команда для отладки UI
Пример:uitest Slider- откроет тестовые окна для проверки UI~(тильда/ё) - открывает консоль клиента
Частые ошибки и решения
1. Элемент не найден в коде
Проблема: MyButton не существует в текущем контексте.
Решение: Убедитесь, что:
- У элемента есть атрибут
Name="MyButton" - Класс имеет атрибут
[GenerateTypedNameReferences] - Вызов
RobustXamlLoader.Load(this)есть в конструкторе
2. XAML не загружается
Проблема: Исключение при загрузке XAML.
Решение: Проверьте:
- Правильность XML синтаксиса
- Все xmlns ссылки корректны
- Все типы элементов существуют
3. Окно не открывается
Проблема: Окно создаётся, но не отображается.
Решение: Убедитесь, что вызываете Open():
var window = new MyWindow();
window.Open(); // Важно!
4. События не работают
Проблема: Обработчик события не вызывается.
Решение: Проверьте, что подписка на событие происходит после RobustXamlLoader.Load(this):
public MyWindow()
{
RobustXamlLoader.Load(this); // Сначала загрузка
MyButton.OnPressed += OnPressed; // Потом подписка
}
Дополнительные ресурсы
Примечание: Официальная документация SS14 может содержать устаревшую информацию.
Всегда проверяйте актуальность информации в исходном коде проекта.
- Официальная документация UI (Robust Toolbox)
- Примеры UI в SS14 (GitHub)
- UI and You - руководство от разработчиков
Автор гайда
Автор: Кейси
Discord: nimf0374