Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when using a global Style with a switch #24

Open
gchapeaux opened this issue Jan 8, 2025 · 2 comments
Open

Crash when using a global Style with a switch #24

gchapeaux opened this issue Jan 8, 2025 · 2 comments

Comments

@gchapeaux
Copy link

gchapeaux commented Jan 8, 2025

THE ISSUE

I was trying to define a style for my switches in a Style.xaml file as follows :

<Style TargetType="switch:CustomSwitch">
    <Setter Property="KnobBackgroundColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource Gray100}}"/>
    <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray100}, Dark={StaticResource MidnightBlue}}"/>
    <Setter Property="KnobHeight" Value="34"/>
    <Setter Property="KnobWidth" Value="34"/>
    <Setter Property="KnobLimit" Value="Max"/>
    <Setter Property="StrokeShape">
        <RoundRectangle CornerRadius="10" />
    </Setter>
    <Setter Property="KnobStrokeShape">
        <RoundRectangle CornerRadius="17" />
    </Setter>
</Style>

In my page, I use my switch as follows :

<VerticalStackLayout>
    <Label 
        Text="Welcome to .NET MAUI!"
        VerticalOptions="Center" 
        HorizontalOptions="Center" />
    
    <switch:CustomSwitch x:Name="ThemeSwitch" HeightRequest="30" WidthRequest="60"/>
</VerticalStackLayout>

When I run my project, the app crashes, and I end up having this exception :

[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
[mono-rt]  ---> System.NullReferenceException: Object reference not set to an instance of an object.
[mono-rt]    at IeuanWalker.Maui.Switch.CustomSwitch.SizeRequestChanged(BindableObject bindable, Object oldValue, Object newValue)
[mono-rt]    at Microsoft.Maui.Controls.BindableObject.OnBindablePropertySet(BindableProperty property, Object original, Object value, Boolean didChange, Boolean willFirePropertyChanged) in /_/src/Controls/src/Core/BindableObject.cs:line 675
[mono-rt]    at Microsoft.Maui.Controls.Element.OnBindablePropertySet(BindableProperty property, Object original, Object value, Boolean changed, Boolean willFirePropertyChanged) in /_/src/Controls/src/Core/Element/Element.cs:line 642
[mono-rt]    at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, Boolean silent) in /_/src/Controls/src/Core/BindableObject.cs:line 662
[mono-rt]    at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity) in /_/src/Controls/src/Core/BindableObject.cs:line 590
[mono-rt]    at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, SetterSpecificity specificity) in /_/src/Controls/src/Core/BindableObject.cs:line 524

MY INVESTIGATION

I tried to figure out on my own what the issue was, just to verify if it was on my end or from the plugin side, and it turns out the exception is raised in CustomSwitch.xaml.cs, in SizeRequestChanged, because view.KnobFrame and view.BackgroundFrame are null.
I tried to fix it by adding hasLoaded to if(bindable is not CustomSwitch view || !view.HasLoaded), but it caused the switches to generate in some situations with styles apparently not being applied at all :

image

EXAMPLE REPO

Check this repository for bug reproduction.

@IeuanWalker
Copy link
Owner

IeuanWalker commented Jan 8, 2025

@gchapeaux sorry been pretty busy with work recently, will see if i have time to look at it over the weekend.

Is there a reason u need it too work via styles.xaml?

I tend to wrap most controls in a ContentView, which then allows you to only expose the properties you want access to via the rest of the app. So other developers cant change the style of a control else where. Also means you can switch out the underlying control if ever needed and remap properties to a new control.

F.e. all the demo/ example switches uses this approach - https://github.com/IeuanWalker/Maui.Switch/blob/master/Demo/App/Controls/CustomSwitchExamples/IosSwitch.xaml

I also recommend this approach on my other controls too - https://github.com/IeuanWalker/Maui.StateButton?tab=readme-ov-file#recomended-usage

@gchapeaux
Copy link
Author

@gchapeaux sorry been pretty busy with work recently, will see if i have time to look at it over the weekend.

Is there a reason u need it too work via styles.xaml?

I tend to wrap most controls in a ContentView, which then allows you to only expose the properties you want access to via the rest of the app. So other developers cant change the style of a control else where. Also means you can switch out the underlying control if ever needed and remap properties to a new control.

F.e. all the demo/ example switches uses this approach - https://github.com/IeuanWalker/Maui.Switch/blob/master/Demo/App/Controls/CustomSwitchExamples/IosSwitch.xaml

I also recommend this approach on my other controls too - https://github.com/IeuanWalker/Maui.StateButton?tab=readme-ov-file#recomended-usage

I have been using styles in my app from the beginning, plus I have two complemetary apps referencing the same style file, so I figured I'd be doing this for switches as well. I'll have a look at Control templates, it could be a workaround in the meantime ! Thanks for the reply !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants