I want to make a xaml style for a circle button. A circle button would have equal width and height, and a corner radius of half the width. I would like to have a style where I only need to set one property, like the WidthRequest, and the other properties are calculated based on the property I set. So ideally I could have
<Button WidthRequest="120"
Style="{StaticResource Circle}"/>
So the height and width would reference each other, and the corner radius would use the math converter to half the width. Something like
<Style x:Key="Square"
TargetType="View">
<Setter Property="WidthRequest" Value="{Binding HeightRequest, Source={RelativeSource Self}}"/>
<Setter Property="HeightRequest" Value="{Binding WidthRequest, Source={RelativeSource Self}}"/>
</Style>
<Style x:Key="Circle"
BasedOn="{StaticResource Square}"
TargetType="Button">
<Setter Property="CornerRadius" Value="{Binding WidthRequest, Source={RelativeSource Self}, Converter={StaticResource toolkit:MathExpressionConverter}, ConverterParameter='x/2'}"/>
</Style>
However, The self reference in the style sheet references the Setter, instead of the control that consumes the style.
As a work around I have a CircleButton control, below. This works but I'd prefer to use a style instead of a custom control
<?xml version="1.0" encoding="utf-8" ?>
<Button xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.CircleButton"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
WidthRequest="{Binding HeightRequest, Source={RelativeSource Self}}"
HeightRequest="{Binding WidthRequest, Source={RelativeSource Self}}"
CornerRadius="{Binding WidthRequest, Source={RelativeSource Self}, Converter={StaticResource MathExpressionConverter}, ConverterParameter='x/2'}">
<Button.Resources>
<ResourceDictionary>
<toolkit:MathExpressionConverter x:Key="MathExpressionConverter" />
</ResourceDictionary>
</Button.Resources>
</Button>
I noticed how you're instantiating the Converter as
Converter={StaticResource toolkit:MathExpressionConverter}
Usually you put an instance in your own ResourceDictionary and instantiate it like this:
Converter={StaticResource MathExpressionConverter}
A full ResourceDictionary would look like:
<ResourceDictionary>
<!-- Insert the MathExpressionConverter into your resource dictionary -->
<toolkit:MathExpressionConverter x:Key="MathExpressionConverter" />
<!-- Your original Square definition -->
<Style x:Key="Square" TargetType="View">
<Setter Property="WidthRequest" Value="{Binding HeightRequest, Source={RelativeSource Self}}" />
<Setter Property="HeightRequest" Value="{Binding WidthRequest, Source={RelativeSource Self}}" />
</Style>
<!-- Updated Circle definition -->
<Style
x:Key="Circle"
BasedOn="{StaticResource Square}"
TargetType="Button">
<!-- Use your instance of the MathExpressionConverter here -->
<Setter Property="CornerRadius" Value="{Binding Width, Source={RelativeSource Self}, Converter={StaticResource MathExpressionConverter}, ConverterParameter='x/2'}" />
</Style>
</ResourceDictionary>