lepoco/wpfui · error · InvalidOperationException

The {pageType} page does not have a parameterless constructo

Error message

The {pageType} page does not have a parameterless constructor or the required services have not been configured for dependency injection. Use the static {nameof(ControlsServices)} class to initialize the GUI library with your service provider. If you are using {typeof(INavigationViewPageProvider)} do not navigate initially and don't use Cache or Precache.

What it means

Thrown when ControlsServices.ControlsServiceProvider is initialized (the DI branch is active) and a page has only parameterized constructors, but none of them can be fully satisfied by the registered services plus the optional dataContext. FitBestConstructor scores each constructor by how many parameters ResolveConstructorParameter can resolve and discards any constructor that is not 100% satisfiable, so the error fires when every constructor has at least one unresolvable parameter.

Source

Thrown at src/Wpf.Ui/Controls/NavigationView/NavigationViewActivator.cs:63

        FrameworkElement? instance;

#if NET48_OR_GREATER || NETCOREAPP3_0_OR_GREATER
        if (ControlsServices.ControlsServiceProvider != null)
        {
            ConstructorInfo[] pageConstructors = pageType.GetConstructors();
            var parameterlessCount = pageConstructors.Count(ctor => ctor.GetParameters().Length == 0);
            var parameterfullCount = pageConstructors.Length - parameterlessCount;

            if (parameterlessCount == 1)
            {
                instance = InvokeParameterlessConstructor(pageType);
            }
            else if (parameterlessCount == 0 && parameterfullCount > 0)
            {
                ConstructorInfo? selectedCtor =
                    FitBestConstructor(pageConstructors, dataContext)
                    ?? throw new InvalidOperationException(
                        $"The {pageType} page does not have a parameterless constructor or the required services have not been configured for dependency injection. Use the static {nameof(ControlsServices)} class to initialize the GUI library with your service provider. If you are using {typeof(INavigationViewPageProvider)} do not navigate initially and don't use Cache or Precache."
                    );
                instance = InvokeElementConstructor(selectedCtor, dataContext);
                SetDataContext(instance, dataContext);

                return instance;
            }
        }
        else if (dataContext != null)
#else
        if (dataContext != null)
#endif
        {
            instance = InvokeElementConstructor(pageType, dataContext);

            if (instance != null)
            {
                return instance;

View on GitHub (pinned to ffebacd610)

Solutions

  1. Register every constructor-injected dependency of the page in the service provider passed to ControlsServices.Initialize.
  2. Match the exact parameter type (interface vs implementation) that the constructor asks for.
  3. Add a parameterless constructor to the page so the activator can fall back to it.
  4. If using a custom INavigationViewPageProvider, do not trigger initial navigation, Cache, or Precache - resolve pages yourself.

Example fix

// before
services.AddSingleton<INavigationViewPageProvider, PageService>();
// page ctor: public DashboardPage(IOrderRepo repo) - IOrderRepo not registered

// after
services.AddSingleton<IOrderRepo, OrderRepo>();
services.AddSingleton<INavigationViewPageProvider, PageService>();
ControlsServices.Initialize(services.BuildServiceProvider());
Defensive patterns

Strategy: validation

Validate before calling

// Validate each page ctor parameter is resolvable before navigating.
foreach (var ctor in typeof(TPage).GetConstructors())
{
    var missing = ctor.GetParameters()
        .Where(p => sp.GetService(p.ParameterType) is null)
        .Select(p => p.ParameterType.Name);
    if (missing.Any()) throw new InvalidOperationException($"Unregistered deps: {string.Join(", ", missing)}");
}

Type guard

static bool AllCtorParamsResolvable(Type page, IServiceProvider sp) =>
    page.GetConstructors().Any(c => c.GetParameters().All(p => sp.GetService(p.ParameterType) is not null));

Try / catch

try { navView.Navigate<TPage>(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("required services have not been configured"))
{
    _logger.LogError(ex, "DI not configured for {Page}", typeof(TPage));
}

Prevention

When it happens

Trigger: Page constructor requires a service that was never registered in the IServiceProvider passed to ControlsServices; constructor requires a type only resolvable via dataContext but no dataContext was supplied; multiple constructors all blocked by the same missing dependency.

Common situations: Forgetting services.AddSingleton<IMyRepo>() before ControlsServices.Initialize; registering an interface but injecting its concrete implementation (or vice-versa); scoped vs singleton lifetime mismatches that cause GetService to return null; introducing a new constructor parameter and forgetting to register it.

Related errors


AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13). Data as JSON: /api/errors/11a65330035b8889. Report an issue: GitHub.