xaml-csharp-development-skill-for-avalonia

TopLevel, Window, and Runtime Services

Table of Contents

  1. Scope and APIs
  2. TopLevel Runtime Services Surface
  3. TopLevel State, Theme, and Transparency APIs
  4. Window and WindowBase Integration
  5. Window Metadata and Event Argument Tails
  6. Lifetime-Aware Service Access Patterns
  7. Practical Patterns
  8. Troubleshooting

Scope and APIs

Primary app-facing APIs:

Service entry points exposed by TopLevel:

TopLevel Runtime Services Surface

Use TopLevel.GetTopLevel(visual) at runtime, then consume host services from that surface.

var topLevel = TopLevel.GetTopLevel(this);
if (topLevel is null)
    return;

var storage = topLevel.StorageProvider;
var launcher = topLevel.Launcher;
var clipboard = topLevel.Clipboard;
var screens = topLevel.Screens;

Platform/host interop helpers:

Use case examples:

TopLevel State, Theme, and Transparency APIs

Core TopLevel properties/events:

Attached-property helpers:

Pattern:

if (TopLevel.GetTopLevel(this) is { } top)
{
    top.TransparencyBackgroundFallback = Brushes.Black;

    TopLevel.SetAutoSafeAreaPadding(this, true);
    TopLevel.SetSystemBarColor(this, new SolidColorBrush(Colors.Black));
}

Window and WindowBase Integration

WindowBase : TopLevel adds window-host behavior:

Window adds desktop-window semantics:

Constructors frequently used by host integrations:

Window Metadata and Event Argument Tails

Window transparency metadata:

Window icon APIs:

Window event argument tails:

Pattern:

if (topLevel is Window window)
{
    window.TransparencyLevelHint = new WindowTransparencyLevelCollection(new[]
    {
        WindowTransparencyLevel.Mica,
        WindowTransparencyLevel.Blur
    });

    window.Closing += (_, e) =>
    {
        if (e.CloseReason == WindowCloseReason.OSShutdown)
            return;

        if (!e.IsProgrammatic && HasInFlightOperation())
            e.Cancel = true;
    };

    window.Resized += (_, e) =>
    {
        if (e.Reason == WindowResizeReason.User)
            PersistWindowSize(window.ClientSize);
    };
}

Lifetime-Aware Service Access Patterns

In desktop apps, cache only short-lived references to top-level services; resolve from the active TopLevel when needed.

public async Task OpenFromWindowAsync(Window window)
{
    var storage = window.StorageProvider;
    var files = await storage.OpenFilePickerAsync(new FilePickerOpenOptions());
    _ = files.Count;
}

When wiring in Application:

Practical Patterns

  1. Resolve services from the current surface.
    • Avoid static service singletons for Clipboard/Launcher/StorageProvider.
  2. Handle scaling and insets as runtime signals.
    • Subscribe to ScalingChanged and query InsetsManager as layout conditions change.
  3. Keep platform inhibition scopes short.
    • Dispose the handle returned from RequestPlatformInhibition(...) promptly.
  4. Gate platform-handle usage.
    • Treat TryGetPlatformHandle() as optional; include null-safe fallbacks.

Troubleshooting

  1. StorageProvider or Clipboard unavailable.
    • Ensure the control is attached and TopLevel.GetTopLevel(...) is non-null.
  2. Theme/transparency mismatch.
    • Check RequestedThemeVariant, ActualThemeVariant, TransparencyLevelHint, and ActualTransparencyLevel together.
  3. Window activation behavior inconsistent.
    • Inspect IsActive, Topmost, Owner, and WindowState transitions.
  4. Host-specific API behavior differs across platforms.
    • Expected; use the portable TopLevel/WindowBase surface first and keep platform specifics isolated.