Skip to content

XSG drops Trigger.Setters.Add() for Shell Tab Icons when using implicit xmlns - 10.0.40 #34039

@bcaceiro

Description

@bcaceiro

Description

When using MauiXamlInflator=SourceGen (the XAML Source Generator) together with MauiAllowImplicitXmlnsDeclaration (no explicit xmlns / xmlns:x declarations), the XSG fails to emit trigger.Setters.Add(setter) calls for Setter objects inside Style.Triggers on Shell Tab elements.

The result is that triggers are added to the style with empty Setters collections, so the FontImageSource icons are never applied and no icons render on the bottom tab bar.

The same XAML works correctly when:

  • Using the runtime inflator (Inflator="Default")
  • Using explicit xmlns="http://schemas.microsoft.com/dotnet/2021/maui" and xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" declarations (the XSG then correctly emits Setters.Add())

This is a regression introduced in .NET MAUI 10.0.40 SR4. The same XAML pattern worked correctly in 10.0.31.

Steps to Reproduce

  1. Clone this repo. The project structure is:

    • XsgShellTabIconsBug/ - MAUI Shell app (net10.0-android)
    • SharedLib/ - Class library with static icon constants (cross-assembly x:Static)
  2. Build and deploy to an Android device:

    cd XsgShellTabIconsBug
    dotnet build XsgShellTabIconsBug.csproj -f net10.0-android -t:Run --no-incremental
  3. Observe that no icons are shown on the bottom tab bar

Key XAML pattern in AppShell.xaml:

<!-- No explicit xmlns or xmlns:x - using MauiAllowImplicitXmlnsDeclaration -->
<Shell x:Class="XsgShellTabIconsBug.AppShell"
       xmlns:local="clr-namespace:XsgShellTabIconsBug"
       xmlns:shared="clr-namespace:SharedLib;assembly=SharedLib"
       Shell.FlyoutBehavior="Disabled">

    <ShellContent Title="Home" ContentTemplate="{DataTemplate local:HomePage}" Route="LoadingPage" />

    <TabBar>
        <Tab Title="{x:Static shared:IconConstants.HomeGlyph}" Route="HomePage">
            <Tab.Style>
                <Style TargetType="Tab">
                    <Style.Triggers>
                        <Trigger TargetType="Tab" Property="IsChecked" Value="True">
                            <Setter Property="Icon">
                                <Setter.Value>
                                    <FontImageSource FontFamily="OpenSansSemibold"
                                                     Glyph="{x:Static shared:IconConstants.HomeGlyph}"
                                                     Size="{OnPlatform Android=16, iOS=20}" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <!-- ... IsChecked=False trigger with FARegular ... -->
                    </Style.Triggers>
                </Style>
            </Tab.Style>
            <ShellContent Title="Home" ContentTemplate="{DataTemplate local:HomePage}" />
        </Tab>
    </TabBar>
</Shell>

Link to public reproduction project repository

https://github.com/bcaceiro/net9-repros/tree/main/XsgShellTabIconsBug

Version with bug

10.0.40

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

10.0.30

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

Per-file opt-out from XSG for the AppShell:

<!-- In your .csproj -->
<ItemGroup>
    <MauiXaml Update="AppShell.xaml" Inflator="Default" />
</ItemGroup>

This forces the runtime XAML inflator for AppShell.xaml only, while keeping XSG enabled for all other pages.

Relevant log output

The project has `<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>` enabled. After building, inspect the XSG output at:


obj/Debug/net10.0-android/generated/Microsoft.Maui.Controls.SourceGen/
  Microsoft.Maui.Controls.SourceGen.XamlGenerator/AppShell.xaml.xsg.cs


### Broken output (implicit xmlns - current behavior)

When `xmlns` and `xmlns:x` are **omitted** (relying on `MauiAllowImplicitXmlnsDeclaration`), the XSG generates:


// Setter is created and fully configured...
var setter = new Setter();
setter.Property = BaseShellItem.IconProperty;
fontImageSource.SetValue(FontImageSource.FontFamilyProperty, "OpenSansSemibold");
fontImageSource.SetValue(FontImageSource.GlyphProperty, staticExtension1);
fontImageSource.SetValue(FontImageSource.SizeProperty, 16D);
setter.Value = (object)fontImageSource;

// BUG: trigger.Setters.Add(setter) is MISSING here!

// Trigger added to style with EMPTY Setters collection
var iList = style1.Triggers;
iList.Add(trigger1);


The `setter` is created and configured but **never added to `trigger1.Setters`**. The trigger goes into the style with an empty Setters collection, so the Icon property is never set.

### Working output (explicit xmlns)

When adding explicit `xmlns="http://schemas.microsoft.com/dotnet/2021/maui"` and `xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"`, the XSG generates correct code:


// Setter created and configured
var setter = new Setter();
setter.Property = BaseShellItem.IconProperty;
fontImageSource.SetValue(FontImageSource.FontFamilyProperty, "OpenSansSemibold");
fontImageSource.SetValue(FontImageSource.GlyphProperty, staticExtension1);
fontImageSource.SetValue(FontImageSource.SizeProperty, 16D);
setter.Value = (object)fontImageSource;

// Correctly adds setter to trigger
var setter4 = new Setter { Property = BaseShellItem.IconProperty, Value = fontImageSource };
trigger1.Setters.Add(setter4);

var iList = style1.Triggers;
iList.Add(trigger1);

Metadata

Metadata

Labels

i/regressionThis issue described a confirmed regression on a currently supported versionplatform/androidregressed-in-10.0.40s/triagedIssue has been revieweds/verifiedVerified / Reproducible Issue ready for Engineering Triaget/bugSomething isn't workingxsgXaml sourceGen

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions