Skip to content

NativeAOT/trimming warnings with AsyncNavigation.Avalonia 2.0.2 and Avalonia 12.1.3 #60

Open

Description

@RoccoZero

The README advertises full Avalonia NativeAOT/trimming support without extra configuration. Publishing a minimal application using AsyncNavigation.Avalonia 2.0.2 with Avalonia 12.1.3 produces IL2026, IL3050, and IL2091 warnings from the navigation packages.

There is no application XAML, reflection binding, warning suppression, or trimmer root descriptor in this reproduction.

Environment

  • Windows x64
  • .NET SDK: 11.0.100-rc.1.26425.128
  • Target framework: net10.0 (the same warnings also appeared in a net11.0-windows application)
  • AsyncNavigation.Avalonia: 2.0.2
  • Avalonia: 12.1.3
  • Microsoft.Extensions.DependencyInjection: 10.0.11

Minimal reproduction

Repro.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <PublishAot>true</PublishAot>
    <IsAotCompatible>true</IsAotCompatible>
    <TrimmerSingleWarn>false</TrimmerSingleWarn>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="AsyncNavigation.Avalonia" Version="2.0.2" />
    <PackageReference Include="Avalonia" Version="12.1.3" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.11" />
  </ItemGroup>
</Project>

Program.cs:

using AsyncNavigation;
using AsyncNavigation.Abstractions;
using Avalonia.Controls;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();
services.AddNavigationSupport().RegisterNavigation<SampleView, SampleViewModel>("sample");
using var provider = services.BuildServiceProvider();
Console.WriteLine(provider.GetRequiredService<IRegionManager>().GetType().Name);

public sealed class SampleView : UserControl, IView;

public sealed class SampleViewModel : NavigationAwareBase;

Publish:

dotnet publish Repro.csproj -c Release -r win-x64

The publication succeeds. The resulting native executable also exits successfully and prints RegionManager. This reproduction checks registration/resolution only; it does not establish that every navigation or dialog feature fails at runtime.

Observed diagnostics

Location Warnings Reported operation
ContentRegion.InitializeOnRegionCreated IL2026, IL3050 Avalonia.Data.Binding.Binding(string)
ItemsRegionBase.InitializeOnRegionCreated, TabRegion.InitializeOnRegionCreated, TabbedPageRegion.InitializeOnRegionCreated IL2026, IL3050 Avalonia.Data.Binding.Binding(string)
IconResolver.ResolveResourceKey, IconResolver.ResolvePathData IL2026, IL3050 Avalonia.Data.Binding.Binding(string)
DefaultDialogContainer.!XamlIlPopulate IL2026, IL3050 ReflectionBindingExtension(string)
RegisterViewModelAndView<TView, TViewModel, TAware> IL2091 for both TView and TViewModel Generic arguments do not satisfy the PublicConstructors requirement of AddTransient<TService>
AddNavigationSupport and the registration call in Program.cs IL3050 System.Enum.GetValues(Type)

Representative messages, with local paths omitted:

IL2026: AsyncNavigation.Avalonia.ContentRegion.InitializeOnRegionCreated(ContentControl):
Using member 'Avalonia.Data.Binding.Binding(String)' which has
'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.

IL3050: AsyncNavigation.Avalonia.ContentRegion.InitializeOnRegionCreated(ContentControl):
Using member 'Avalonia.Data.Binding.Binding(String)' which has
'RequiresDynamicCodeAttribute' can break functionality when AOT compiling.

IL2091: RegisterViewModelAndView<TView,TViewModel,TAware>:
The generic parameter 'TView' does not have matching annotations for
'DynamicallyAccessedMemberTypes.PublicConstructors' required by AddTransient<TService>.
The same warning is reported for 'TViewModel'.

IL3050: AddNavigationSupport(IServiceCollection,NavigationOptions):
Using member 'System.Enum.GetValues(Type)' which has 'RequiresDynamicCodeAttribute'.

Expected behavior / possible fixes

NativeAOT publication should not require applications to suppress these warnings to use the advertised supported configuration.

Could the internal code bindings and dialog XAML use compiled/typed bindings, and could the required constructor-preservation annotations be propagated through the private RegisterViewModelAndView helper? The Enum.GetValues(Type) diagnostic also needs investigation; I have not identified its exact underlying source call.

Enabling the trimming/AOT analyzers for the packages and adding a small NativeAOT publication test would help catch regressions. If this Avalonia version is outside the supported compatibility range, please document that range instead.

Activity

  1. RoccoZero commented on Oct 8, 2026

    @RoccoZero
    Author

    Here is a tested patch for the region bindings and default dialog title from this report. It targets the 2.0.2 source revision 99f457b685f4315db586ce8d0d9f83cf176d9723.

    The seven code bindings use CompiledBinding.Create with typed RegionContext expressions. Their existing sources and binding modes are preserved, including TwoWay selection. The dialog XAML uses IDialogAware as its data type and a compiled Title binding.

    Patch

    diff --git a/src/AsyncNavigation.Avalonia/ContentRegion.cs b/src/AsyncNavigation.Avalonia/ContentRegion.cs
    index 3c2a8ea..023f79f 100644
    --- a/src/AsyncNavigation.Avalonia/ContentRegion.cs
    +++ b/src/AsyncNavigation.Avalonia/ContentRegion.cs
    @@ -32,7 +32,7 @@ public class ContentRegion : RegionBase<ContentRegion, ContentControl>
     
             control.Bind(
                 ContentControl.ContentProperty,
    -            new Binding(nameof(RegionContext.Selected)) { Source = _context, Mode = BindingMode.TwoWay });
    +            CompiledBinding.Create((RegionContext context) => context.Selected, _context, mode: BindingMode.TwoWay));
         }
     
         public override void Dispose()
    diff --git a/src/AsyncNavigation.Avalonia/DefaultDialogContainer.axaml b/src/AsyncNavigation.Avalonia/DefaultDialogContainer.axaml
    index 8fa7705..b50d2c3 100644
    --- a/src/AsyncNavigation.Avalonia/DefaultDialogContainer.axaml
    +++ b/src/AsyncNavigation.Avalonia/DefaultDialogContainer.axaml
    @@ -4,7 +4,9 @@
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    -    Title="{ReflectionBinding Title}"
    +    xmlns:nav="clr-namespace:AsyncNavigation.Abstractions;assembly=AsyncNavigation"
    +    x:DataType="nav:IDialogAware"
    +    Title="{CompiledBinding Title}"
         d:DesignHeight="450"
         d:DesignWidth="800"
         mc:Ignorable="d" />
    diff --git a/src/AsyncNavigation.Avalonia/ItemsRegionBase.cs b/src/AsyncNavigation.Avalonia/ItemsRegionBase.cs
    index c2141a7..76e72ef 100644
    --- a/src/AsyncNavigation.Avalonia/ItemsRegionBase.cs
    +++ b/src/AsyncNavigation.Avalonia/ItemsRegionBase.cs
    @@ -37,7 +37,7 @@ public abstract class ItemsRegionBase<TRegion, TItemsControl>
     
             control.Bind(
                 ItemsControl.ItemsSourceProperty,
    -            new Binding(nameof(RegionContext.Items)) { Source = _context });
    +            CompiledBinding.Create((RegionContext context) => context.Items, _context));
         }
     
     
    diff --git a/src/AsyncNavigation.Avalonia/TabRegion.cs b/src/AsyncNavigation.Avalonia/TabRegion.cs
    index 3ae89ea..a6b777b 100644
    --- a/src/AsyncNavigation.Avalonia/TabRegion.cs
    +++ b/src/AsyncNavigation.Avalonia/TabRegion.cs
    @@ -26,10 +26,10 @@ public class TabRegion : RegionBase<TabRegion, TabControl>
             base.InitializeOnRegionCreated(control);
             control.Tag = this;
             control.Bind(ItemsControl.ItemsSourceProperty,
    -            new Binding(nameof(RegionContext.Items)) { Source = _context });
    +            CompiledBinding.Create((RegionContext context) => context.Items, _context));
     
             control.Bind(SelectingItemsControl.SelectedItemProperty,
    -            new Binding(nameof(RegionContext.Selected)) { Source = _context, Mode = BindingMode.TwoWay });
    +            CompiledBinding.Create((RegionContext context) => context.Selected, _context, mode: BindingMode.TwoWay));
     
             control.ContentTemplate = new FuncDataTemplate<NavigationContext>((context, _) =>
             {
    diff --git a/src/AsyncNavigation.Avalonia/TabbedPageRegion.cs b/src/AsyncNavigation.Avalonia/TabbedPageRegion.cs
    index cafbac4..9264780 100644
    --- a/src/AsyncNavigation.Avalonia/TabbedPageRegion.cs
    +++ b/src/AsyncNavigation.Avalonia/TabbedPageRegion.cs
    @@ -29,12 +29,12 @@ public class TabbedPageRegion : RegionBase<TabbedPageRegion, TabbedPage>
             base.InitializeOnRegionCreated(control);
             control.Tag = this;
             control.Bind(TabbedPage.ItemsSourceProperty,
    -            new Binding(nameof(RegionContext.Items)) { Source = _context });
    +            CompiledBinding.Create((RegionContext context) => context.Items, _context));
     
             control.Bind(TabbedPage.CurrentPageProperty,
    -            new Binding(nameof(RegionContext.Selected)) { Source = _context, Mode = BindingMode.TwoWay });
    +            CompiledBinding.Create((RegionContext context) => context.Selected, _context, mode: BindingMode.TwoWay));
     
    -        control.Bind(TabbedPage.HeaderProperty, new Binding(nameof(RegionContext.Selected)) { Source = _context, Mode = BindingMode.TwoWay });
    +        control.Bind(TabbedPage.HeaderProperty, CompiledBinding.Create((RegionContext context) => context.Selected, _context, mode: BindingMode.TwoWay));
             control.PageTemplate = new FuncDataTemplate<NavigationContext>((context, _) =>
             {
                 var page = new ContentPage

    Validation

    • All four modified region classes and the modified dialog XAML compile with the trimming/AOT analyzers enabled; IL2026, IL3050, and IL2091 are treated as errors.
    • An isolated Avalonia Headless test passed 14 binding checks on both Avalonia 12.0.1 (the package's dependency version) and 12.1.3.
    • The 12.1.3 test was also published with NativeAOT (net11.0, win-x64, SDK 11.0.100-rc.1.26425.128) without trimming/AOT diagnostics, and the native executable passed the same 14 checks.
    • Checks cover Content/Selected and selected-tab updates in both directions, null selection, collection notifications, Header updates, property notifications from a background thread, and dialog Title updates through the compiled interface binding.
    • The diff passes git apply --check against the 2.0.2 source.

    This verifies the binding primitives and compiled dialog XAML; it is not a full end-to-end test of every navigation or dialog lifecycle.

    This is a partial fix for #60: the two ancestor Foreground bindings in IconResolver, the private DI helper's constructor-preservation annotations, and the Enum.GetValues(Type) diagnostic still need separate fixes. No warning suppression or application trimmer roots are added by this patch.

    I also submitted the separate shutdown/disposal candidate patch in #61.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions