maui: Some properties not updating (eg VisualState setter not working for Button BackgroundColor) with AOT enabled
Description
The setter is not working properly when in release mode. In debug it works fine. Only noticed it for the backgroundcolor on button. TextColor works fine for button. Didn’t test anything other. Also only tested on android, don’t now if it’s the same for other platforms.
I created a simple project to demonstrate. It’s basicly the templete that you get when createing a new project with added checkbox to enable/disable the button:
<CheckBox x:Name="checkBox" />
<Button
x:Name="CounterBtn"
Text="Click me"
HorizontalOptions="Center"
IsEnabled="{Binding Source={x:Reference checkBox}, Path=IsChecked}"/>
| Before | Debug | Release |
|---|---|---|
![]() |
![]() |
![]() |
Only the text color changed but the background didn’t in release mode.
Steps to Reproduce
- Download linked project
- Set to release mode
- Run on local android device
- Click the checkbox to enable/disable the button
- See results
Link to public reproduction project repository
https://github.com/Kaiffa/maui-bug-visualstate-button-release
Version with bug
7.0 (current)
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
Android 12.0
Did you find any workaround?
Remapping the property from BackgroundColor to Background fixed the issue. This is easy to do in the maui program app builder:
.ConfigureMauiHandlers(_ =>
{
LabelHandler.Mapper.AppendToMapping(
nameof(View.BackgroundColor),
(handler, View) => handler.UpdateValue(nameof(IView.Background)));
ButtonHandler.Mapper.AppendToMapping(
nameof(View.BackgroundColor),
(handler, View) => handler.UpdateValue(nameof(IView.Background)));
})
Relevant log output
Visual studio 17.4.1
Android device used:
Samsung Galaxy A13, Android 12
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 5
- Comments: 32 (14 by maintainers)



Can this be backported when the PR is complete to .Net 7 please
We are also facing this in iOS for all buttons in our app in release mode where they use Visual state
I found a workaround for now that is quite simple:
Remapping the property from BackgroundColor to Background fixed the issue. This is easy to do in the maui program app builder:
After a vast amount of logging in places, I found that AOT affected the order of types being referenced - and thus our static fields were being initialized in “incorrect” orders.
This happened in our “Remap for Controls” section and in most cases we were replacing fields instead of adding properties. We had the correct order in Debug because we were maybe lucky, but the AOT compiler rather went by assembly at a time instead of JIT field init.
In any case, the contents of the mappers should not be affected by the order of the references. I can actually replicate the same issue if I add this code before anything in the MauiProgram:
The issue is pretty simple now that I know what it is 😃
The mappers are set up in Core like this:
This seems like it may work, but what is actually happening in 4-6 is that the field is replaced instead of being appended. This results in step 5 (Element.ControlsElementMapper) adding fields that never make it to the Button.ControlsButtonMapper because that init code has already run and copied the old mapper from 3.
Going to look at the best way to fix this to avoid order-based-init.
I could start working on this next week. First, I will be working on creating an app hopefully a desktop app, which could reproduce this issue. That would be easier for me to debug Mono with.
The only thing you need to make sure if you are using this workaround is that from now wards you need to use Backgroud property to change/set backgroundcolor property of Button. Setting BackgroundColor will have no effect and will be override by the Background value set in ButtonStyle in App.xaml if not explicitly set on particular Button.
Yup For new apps this works good enough
I had to solve it for my customer too, so I disabled AOT compilation in project by adding this line into my CSPROJ file in the first “PropertyGroup”.
<RunAOTCompilation>false</RunAOTCompilation>This was the fastest way to solve it, since the issue is opened for more then half year…
Sorry for the delay. I tried it and this is reproducible locally. I also tried using logging
adb shell setprop debug.mono.log default,assembly,mono_log_level=debug,mono_log_mask=all, which hasn’t provided much outstanding information regarding to the cause of this bug.I am working with @jonathanpeppers and @mattleibow on getting more insights into the problem. Will update once we have more findings.
Hi All,
works for me:
/cc @fanyang-mono
There is a workaround in #8961 that seems to work as well: