Page registration

Register pages automatically or manually and choose transient or singleton behavior.

Navigation needs a mapping between page types and, for MVVM pages, their ViewModel types. The [Page] source generator creates that mapping at compile time without assembly scanning or reflection.

Read pages and lifecycle first if the relationship between ContentView and ContentView<TViewModel> is new.

[Page]
public sealed class LibraryView : ContentView<LibraryViewModel>
{
    public LibraryView(LibraryViewModel viewModel) : base(viewModel)
    {
        Title = "Library";
    }
}

Generated pages are transient by default. Each navigation resolves a ViewModel and constructs a fresh page. This is the safest default because views own native state and should not normally appear in two places.

Singleton pages

Set Singleton when the same page and ViewModel state should remain alive for the application lifetime:

[Page(Singleton = true)]
public sealed class SearchView : ContentView<SearchViewModel>
{
    public SearchView(SearchViewModel viewModel) : base(viewModel) { }
}

Singleton pages are useful for tab roots that must preserve local UI state. They also preserve anything subscribed by that page, so long-lived event handlers and large native resources need the same care as any other singleton.

Constructor rules

A generated view-only page needs an accessible parameterless constructor. A ContentView<TViewModel> page needs an accessible constructor whose first parameter is TViewModel; any remaining parameters must be optional.

The generator reports:

  • SKEL001 when [Page] is placed on a type that is not a ContentView.
  • SKEL002 when the marked page is abstract.
  • SKEL003 when the required constructor is missing.

Manual registration

Use UsePages for factories, existing instances, or construction that the generator cannot express:

SkeleApplication.CreateBuilder()
    .UsePages(pages =>
    {
        pages.AddTransient<EditorViewModel, EditorView>(
            (services, viewModel) => new EditorView(
                viewModel,
                services.GetRequiredService<IEditorOptions>()));

        pages.AddSingleton(new AboutView());
    })
    .Stack<HomeView>()
    .Build();

Manual registrations made before generated UsePages() take precedence. Pass replace: false to the builder overload when adding defaults that should not override an existing mapping.

AddTransient creates a page per navigation. AddSingleton constructs it once on first use, unless an existing instance was supplied.

Once a page is registered, navigation stacks explains the ViewModel-first and view-first ways to open it.