Introduction
Welcome to the UI tutorial for the .NET Gaming platform. In this guide you’ll learn how to create responsive game menus, HUDs, and interactive dialogs using XAML and C#.
XAML UI Basics
Creating a Simple Menu
Define your UI layout in XAML. The GamePage
serves as the root container.
<GamePage xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Main Menu" FontSize="48" Margin="0,0,0,30"/>
<Button Content="Start Game" Width="200" Margin="0,5"/>
<Button Content="Options" Width="200" Margin="0,5"/>
<Button Content="Exit" Width="200" Margin="0,5"/>
</StackPanel>
</GamePage>
Binding Data
Use INotifyPropertyChanged
in your view model to update UI elements dynamically.
public class MenuViewModel : INotifyPropertyChanged
{
private string _title = "Main Menu";
public string Title
{
get => _title;
set { _title = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string name = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
Input Handling
Keyboard, mouse, and gamepad input are routed through the GameInput
service.
public sealed class InputHandler : IGameComponent
{
public void Update(GameTime time)
{
if (GameInput.IsKeyPressed(Keys.Enter))
{
// Start the game
}
if (GameInput.Gamepad.Buttons.Start == ButtonState.Pressed)
{
// Open options
}
}
}
Custom Controls
Create reusable controls by extending Control
and defining a default style.
public class AnimatedButton : Button
{
public AnimatedButton()
{
this.DefaultStyleKey = typeof(AnimatedButton);
}
protected override void OnPointerEntered(PointerRoutedEventArgs e)
{
VisualStateManager.GoToState(this, "PointerOver", true);
base.OnPointerEntered(e);
}
}
Define the visual states in Generic.xaml
:
<Style TargetType="local:AnimatedButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:AnimatedButton">
<Grid>
<Border x:Name="Border"
Background="{TemplateBinding Background}"
CornerRadius="6"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation To="#FF4CAF50"
Duration="0:0:0.2"
Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample Project
Download the complete UI sample from the GitHub repository or clone it:
git clone https://github.com/dotnet/gaming-samples.git
cd gaming-samples/UI
dotnet build
dotnet run