AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.04k stars 2.25k forks source link

Error when OnPlatform doesn't match #17562

Open halfninja opened 2 days ago

halfninja commented 2 days ago

Describe the bug

I'd written a style with an override for when the window is maximised in Windows:

<Style Selector="ToggleButton:checked ContentPresenter">
    <Setter Property="BorderThickness" Value="3 0 0 0" />                  
</Style>
<OnPlatform>
    <OnPlatform.Windows>
        <Style Selector="Window[WindowState=Maximized]">
            <Style Selector="^ ToggleButton:checked ContentPresenter">
                <Setter Property="BorderThickness" Value="10 0 0 0" />                  
            </Style>
        </Style>
    </OnPlatform.Windows>
</OnPlatform>

Works fine on Windows. When I start the app on Macos (or probably any other platform) I get this ominous exception

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at Avalonia.Styling.Styles.TryGetResource(Object key, ThemeVariant theme, Object& value)
   at Avalonia.Application.TryGetResource(Object key, ThemeVariant theme, Object& value)
   at Avalonia.Controls.ResourceNodeExtensions.TryFindResource(IResourceHost control, Object key, ThemeVariant theme, Object& value)
   at Avalonia.Controls.ResourceNodeExtensions.TryFindResource(IResourceHost control, Object key, Object& value)
   at Avalonia.StyledElement.GetEffectiveTheme()
   at Avalonia.StyledElement.ApplyControlTheme()
   at Avalonia.StyledElement.ApplyStyling()
   at Avalonia.StyledElement.EndInit()
   at MyApp.Views.TestWindow.!XamlIlPopulate(IServiceProvider, TestWindow) in /Users/self/Documents/workspace/app/App/Views/TestWindow.axaml:line 7
   at MyApp.Views.TestWindow.!XamlIlPopulateTrampoline(TestWindow)
   at MyApp.Views.TestWindow.InitializeComponent(Boolean loadXaml, Boolean attachDevTools) in /Users/self/Documents/workspace/app/App/obj/Debug/net8.0/Avalonia.Generators/Avalonia.Generators.NameGenerator.AvaloniaNameSourceGenerator/MyApp.Views.TestWindow.g.cs:line 25
   at MyApp.Views.TestWindow..ctor() in /Users/self/Documents/workspace/app/App/Views/TestWindow.axaml.cs:line 11
   at MyApp.App.OnFrameworkInitializationCompleted() in /Users/self/Documents/workspace/app/App/App.axaml.cs:line 117
   at Avalonia.AppBuilder.SetupUnsafe()
   at Avalonia.AppBuilder.Setup()
   at Avalonia.AppBuilder.SetupWithLifetime(IApplicationLifetime lifetime)
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, Action`1 lifetimeBuilder)
   at MyApp.Program.Main(String[] args) in /Users/self/Documents/workspace/app/App.Desktop/Program.cs:line 31

To Reproduce

Define in Application.Styles an OnPlatform element that doesn't match the current platform

Expected behavior

To do nothing when there's no match, or if this usage isn't allowed, to output a meaningful error that explains the mistake. I can add a default match with an unused style in it as a workaround.

Avalonia version

11.2.0

OS

Windows, macOS

Additional context

No response

maxkatz6 commented 2 days ago

To do nothing when there's no match, or if this usage isn't allowed, to output a meaningful error that explains the mistake.

OnPlatform follows ternary operator logic. It always needs to return a value. In this case it's a null. It's still expected to return null as a default in some contexts. We should at least generate a diagnostic error, which can be optionally disabled.

timunie commented 2 days ago
is there for it afaik.
halfninja commented 2 days ago

Thanks both - I did add OnPlatform.Default to fix it as soon as I realised the error, and understood that it was essentially returning null. Could simply be a docs thing - which does have a default case in the example snippets, but perhaps explicitly stating that you likely need to match all platforms in XAML to avoid inserting a null style (though I understand it's not just for styles)