/maui-app-lifecycle
.NET MAUI app lifecycle guidance — the four app states, cross-platform Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying), platform-specific lifecycle mapping, backgrounding and resume behavior, and state-preservation patterns. USE FOR: "app
$ npx -y skills add managedcode/dotnet-skills --skill maui-app-lifecycle --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/maui-app-lifecycle
Context preview
The summary Claude sees to decide when to auto-load this skill.
.NET MAUI app lifecycle guidance — the four app states, cross-platform Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying), platform-specific lifecycle mapping, backgrounding and resume behavior, and state-preservation patterns. USE FOR: "app
SKILL.md
maui-app-lifecycle.SKILL.mdname: maui-app-lifecycle
description: >-
.NET MAUI app lifecycle guidance — the four app states, cross-platform Window
lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying),
platform-specific lifecycle mapping, backgrounding and resume behavior, and
state-preservation patterns.
USE FOR: "app lifecycle", "window lifecycle events", "save state on background",
"resume app", "OnStopped", "OnResumed", "backgrounding", "deactivated event",
"ConfigureLifecycleEvents", "platform lifecycle hooks".
DO NOT USE FOR: navigation events (use maui-shell-navigation),
dependency injection setup (use maui-dependency-injection),
platform API invocation (use conditional compilation and partial classes).
license: MIT
.NET MAUI App Lifecycle
Handle application state transitions correctly in .NET MAUI. This skill covers the cross-platform Window lifecycle events, their platform-native mappings, and patterns for preserving state across backgrounding and resume cycles.
When to Use
- Saving or restoring state when the app backgrounds or resumes
- Subscribing to Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying)
- Hooking into platform-native lifecycle callbacks via `ConfigureLifecycleEvents`
- Deciding where to place initialization, teardown, or refresh logic
- Understanding the difference between Deactivated and Stopped
When Not to Use
- Page-level navigation events — use Shell navigation guidance instead
- Registering services at startup — use dependency injection guidance instead
- Calling platform-specific APIs outside lifecycle context — use platform invoke guidance instead
Inputs
- The target lifecycle transition (e.g., "save draft when backgrounded", "refresh data on resume")
- Which platforms the developer targets (Android, iOS, Mac Catalyst, Windows)
- Whether the app uses multiple windows (iPad, Mac Catalyst, desktop Windows)
App States
A .NET MAUI app moves through four states:
| State | Description | |---|---| | **Not Running** | Process does not exist | | **Running** | Foreground, receiving input | | **Deactivated** | Visible but lost focus (dialog, split-screen, notification shade) | | **Stopped** | Fully backgrounded, UI not visible |
Typical flow: Not Running → Running → Deactivated → Stopped → Running (resumed) or Not Running (terminated).
Window Lifecycle Events
`Microsoft.Maui.Controls.Window` exposes six cross-platform events:
| Event | Fires when | |---|---| | `Created` | Native window allocated | | `Activated` | Window receives input focus | | `Deactivated` | Window loses focus (may still be visible) | | `Stopped` | Window is no longer visible | | `Resumed` | Window returns to foreground after Stopped | | `Destroying` | Native window is being torn down |
Subscribing via CreateWindow
Override `CreateWindow` in your `App` class and attach event handlers:
public partial class App : Application
{
protected override Window CreateWindow(IActivationState? activationState)
{
var window = base.CreateWindow(activationState);
window.Created += (s, e) => Debug.WriteLine("Created");
window.Activated += (s, e) => Debug.WriteLine("Activated");
window.Deactivated += (s, e) => Debug.WriteLine("Deactivated");
window.Stopped += (s, e) => Debug.WriteLine("Stopped");
window.Resumed += (s, e) => Debug.WriteLine("Resumed");
window.Destroying += (s, e) => Debug.WriteLine("Destroying");
return window;
}
}Subscribing via a Custom Window Subclass
Create a `Window` subclass and override the virtual methods:
public class AppWindow : Window
{
public AppWindow(Page page) : base(page) { }
protected override void OnActivated() { /* refresh UI */ }
protected override void OnStopped() { /* save state */ }
protected override void OnResumed() { /* restore state */ }
protected override void OnDestroying() { /* cleanup */ }
}Return it from `CreateWindow`:
protected override Window CreateWindow(IActivationState? activationState)
=> new AppWindow(new AppShell());Workflow: Save and Restore State on Background
1. **Identify transient state** — draft text, scroll position, form inputs, timer values. 2. **Save in `OnStopped`** — use `Preferences` for small values or file serialization for larger state. 3. **Restore in `OnResumed`** — read back saved values and apply to your view model. 4. **Also save in `OnDestroying`** on Android — the back button can skip `Stopped` entirely. 5. **Keep handlers fast** — complete within 1–2 seconds to avoid ANR on Android or watchdog kills on iOS.
protected override void OnStopped()
{
base.OnStopped();
Preferences.Set("draft_text", _viewModel.DraftText);
Preferences.Set("scroll_y", _viewModel.ScrollY);
}
protected override void OnResumed()
{
base.OnResumed();
_viewModel.DraftText = Preferences.Get("draft_text", string.Empty);
_viewModel.ScrollY = Preferences.Get("scroll_y", 0.0);
}
protected override void OnDestroying()
{
base.OnDestroying();
// Android back-button can skip Stopped
Preferences.Set("draft_text", _viewModel.DraftText);
}Platform Lifecycle Mapping
Android
| Window Event | Android Callback | |---|---| | Created | `OnCreate` | | Activated | `OnResume` | | Deactivated | `OnPause` | | Stopped | `OnStop` | | Resumed | `OnRestart` → `OnStart` → `OnResume` | | Destroying | `OnDestroy` |
iOS / Mac Catalyst
| Window Event | UIKit Callback | `AddiOS` builder method | |---|---|---| | Created | `WillFinishLaunching` / `SceneWillConnect` | `.WillFinishLaunching()` / `.SceneWillConnect()` | | Activated | `DidBecomeActive` | `.OnActivated()` | | Deactivated | `WillResignActive` | `.OnResignActivation()` | | Stopped | `DidEnterBackground` | `.DidEnterBackground()` | | Resumed | `WillEnterForeground` | `.WillEnterForeground()` | | Destroying | `WillT
Read more
name: maui-app-lifecycle description: >- .NET MAUI app lifecycle guidance — the four app states, cross-platform Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying), platform-specific lifecycle mapping, backgrounding and resume behavior, and state-preservation patterns. USE FOR: "app lifecycle", "window lifecycle events", "save state on background", "resume app", "OnStopped", "OnResumed", "backgrounding", "deactivated event", "ConfigureLifecycleEvents", "platform lifecycle hooks". DO NOT USE FOR: navigation events (use maui-shell-navigation), dependency injection setup (use maui-dependency-injection), platform API invocation (use conditional compilation and partial classes). license: MIT
.NET MAUI App Lifecycle
Handle application state transitions correctly in .NET MAUI. This skill covers the cross-platform Window lifecycle events, their platform-native mappings, and patterns for preserving state across backgrounding and resume cycles.
When to Use
- Saving or restoring state when the app backgrounds or resumes
- Subscribing to Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying)
- Hooking into platform-native lifecycle callbacks via `ConfigureLifecycleEvents`
- Deciding where to place initialization, teardown, or refresh logic
- Understanding the difference between Deactivated and Stopped
When Not to Use
- Page-level navigation events — use Shell navigation guidance instead
- Registering services at startup — use dependency injection guidance instead
- Calling platform-specific APIs outside lifecycle context — use platform invoke guidance instead
Inputs
- The target lifecycle transition (e.g., "save draft when backgrounded", "refresh data on resume")
- Which platforms the developer targets (Android, iOS, Mac Catalyst, Windows)
- Whether the app uses multiple windows (iPad, Mac Catalyst, desktop Windows)
App States
A .NET MAUI app moves through four states:
| State | Description | |---|---| | **Not Running** | Process does not exist | | **Running** | Foreground, receiving input | | **Deactivated** | Visible but lost focus (dialog, split-screen, notification shade) | | **Stopped** | Fully backgrounded, UI not visible |
Typical flow: Not Running → Running → Deactivated → Stopped → Running (resumed) or Not Running (terminated).
Window Lifecycle Events
`Microsoft.Maui.Controls.Window` exposes six cross-platform events:
| Event | Fires when | |---|---| | `Created` | Native window allocated | | `Activated` | Window receives input focus | | `Deactivated` | Window loses focus (may still be visible) | | `Stopped` | Window is no longer visible | | `Resumed` | Window returns to foreground after Stopped | | `Destroying` | Native window is being torn down |
Subscribing via CreateWindow
Override `CreateWindow` in your `App` class and attach event handlers:
public partial class App : Application
{
protected override Window CreateWindow(IActivationState? activationState)
{
var window = base.CreateWindow(activationState);
window.Created += (s, e) => Debug.WriteLine("Created");
window.Activated += (s, e) => Debug.WriteLine("Activated");
window.Deactivated += (s, e) => Debug.WriteLine("Deactivated");
window.Stopped += (s, e) => Debug.WriteLine("Stopped");
window.Resumed += (s, e) => Debug.WriteLine("Resumed");
window.Destroying += (s, e) => Debug.WriteLine("Destroying");
return window;
}
}Subscribing via a Custom Window Subclass
Create a `Window` subclass and override the virtual methods:
public class AppWindow : Window
{
public AppWindow(Page page) : base(page) { }
protected override void OnActivated() { /* refresh UI */ }
protected override void OnStopped() { /* save state */ }
protected override void OnResumed() { /* restore state */ }
protected override void OnDestroying() { /* cleanup */ }
}Return it from `CreateWindow`:
protected override Window CreateWindow(IActivationState? activationState)
=> new AppWindow(new AppShell());Workflow: Save and Restore State on Background
1. **Identify transient state** — draft text, scroll position, form inputs, timer values. 2. **Save in `OnStopped`** — use `Preferences` for small values or file serialization for larger state. 3. **Restore in `OnResumed`** — read back saved values and apply to your view model. 4. **Also save in `OnDestroying`** on Android — the back button can skip `Stopped` entirely. 5. **Keep handlers fast** — complete within 1–2 seconds to avoid ANR on Android or watchdog kills on iOS.
protected override void OnStopped()
{
base.OnStopped();
Preferences.Set("draft_text", _viewModel.DraftText);
Preferences.Set("scroll_y", _viewModel.ScrollY);
}
protected override void OnResumed()
{
base.OnResumed();
_viewModel.DraftText = Preferences.Get("draft_text", string.Empty);
_viewModel.ScrollY = Preferences.Get("scroll_y", 0.0);
}
protected override void OnDestroying()
{
base.OnDestroying();
// Android back-button can skip Stopped
Preferences.Set("draft_text", _viewModel.DraftText);
}Platform Lifecycle Mapping
Android
| Window Event | Android Callback | |---|---| | Created | `OnCreate` | | Activated | `OnResume` | | Deactivated | `OnPause` | | Stopped | `OnStop` | | Resumed | `OnRestart` → `OnStart` → `OnResume` | | Destroying | `OnDestroy` |
iOS / Mac Catalyst
| Window Event | UIKit Callback | `AddiOS` builder method | |---|---|---| | Created | `WillFinishLaunching` / `SceneWillConnect` | `.WillFinishLaunching()` / `.SceneWillConnect()` | | Activated | `DidBecomeActive` | `.OnActivated()` | | Deactivated | `WillResignActive` | `.OnResignActivation()` | | Stopped | `DidEnterBackground` | `.DidEnterBackground()` | | Resumed | `WillEnterForeground` | `.WillEnterForeground()` | | Destroying | `WillT
Stop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Repo: managedcode/dotnet-skills
Other skills on dotnet-skills.
- /aspnet-core
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET. USE FOR: working on ASP.NET Core apps, services, or middleware; changing auth, routing, configuration,
Open skill - /aspire
Build, upgrade, and operate Aspire 13.4.x C# or TypeScript application hosts with the current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, MCP, and deployment patterns for distributed apps. USE FOR: Aspire.AppHost.Sdk, Aspire.Hosting.*,
Open skill - /azure-functions
Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable
Open skill - /blazor
Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design, state flow, rendering, and hosting choices. USE FOR: building interactive web UIs with C# instead of JavaScript; choosing between Server, WebAssembly, or
Open skill - /entity-framework6
Maintain or migrate EF6-based applications with realistic guidance on what to keep, what to modernize, and when EF Core is or is not the right next step. USE FOR: EF6 codebases; runtime versus ORM migration decisions; EDMX, code-first, ObjectContext, and legacy data-access
Open skill - /entity-framework-core
Design, tune, or review EF Core data access with proper modeling, migrations, query translation, performance, and lifetime management for modern .NET applications. USE FOR: DbContext, migrations, model configuration, EF queries, tracking, loading, performance, transactions, and
Open skill

