xaml-csharp-development-skill-for-avalonia

Screens and Display Awareness

Table of Contents

  1. Scope and APIs
  2. Screen Model
  3. Monitor-Aware Patterns
  4. Change Tracking Patterns
  5. XAML-First and Code-Only Usage
  6. Best Practices
  7. Troubleshooting

Scope and APIs

Primary APIs:

Important members:

Reference source files:

Screen Model

Use TopLevel.Screens as read model for connected displays.

Model notes:

Monitor-Aware Patterns

using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;

public static class ScreenWorkflows
{
    public static Screen? GetCurrentScreen(Control anchor)
    {
        TopLevel? top = TopLevel.GetTopLevel(anchor);
        return top?.Screens?.ScreenFromVisual(anchor);
    }

    public static PixelRect? GetPrimaryWorkingArea(Control anchor)
    {
        TopLevel? top = TopLevel.GetTopLevel(anchor);
        return top?.Screens?.Primary?.WorkingArea;
    }
}

Change Tracking Patterns

using System;
using Avalonia.Controls;

public sealed class ScreenChangeTracker : IDisposable
{
    private readonly Screens? _screens;
    private readonly EventHandler _handler;

    public ScreenChangeTracker(TopLevel topLevel, Action onChanged)
    {
        _handler = (_, _) => onChanged();
        _screens = topLevel.Screens;
        if (_screens is not null)
            _screens.Changed += _handler;
    }

    public void Dispose()
    {
        if (_screens is not null)
            _screens.Changed -= _handler;
    }
}

XAML-First and Code-Only Usage

Default mode:

XAML-first complete example:

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="using:MyApp.ViewModels"
             x:DataType="vm:DisplayViewModel">
  <StackPanel Margin="12" Spacing="8">
    <Button Content="Refresh Displays" Command="{CompiledBinding RefreshScreensCommand}" />
    <TextBlock Text="{CompiledBinding PrimaryDisplayName}" />
    <TextBlock Text="{CompiledBinding PrimaryWorkingAreaText}" />
  </StackPanel>
</UserControl>

Code-only alternative (on request):

using Avalonia.Controls;

public static class CodeOnlyScreenSample
{
    public static string DescribePrimary(Control anchor)
    {
        TopLevel? top = TopLevel.GetTopLevel(anchor);
        Screen? primary = top?.Screens?.Primary;

        if (primary is null)
            return "No screen information available.";

        return $"{primary.DisplayName} {primary.WorkingArea} scale={primary.Scaling:0.##}";
    }
}

Best Practices

Troubleshooting

  1. Screen query returns null:
    • Visual is not attached to a TopLevel.
    • Platform does not expose that query path.
  2. Window placement looks wrong on multi-monitor setup:
    • Used Bounds where WorkingArea should be used.
    • Ignored per-display scaling.
  3. Display names/details missing:
    • Platform may require explicit RequestScreenDetails() and permission.