.NET MAUI: How to make RadioButton (with ControlTemplate) use all available space?

86 Views Asked by At

I need to display a horizontal selection list where the items are spaced out evenly over the view.
For this purpose I would use a FlexLayout and populate its BindableLayout with the input data for selections.
However, the RadioButton refuses to occupy the whole area and setting the WidthRequest manually is not feasable, because the width of the view or the number of selectable options could vary.

Is there something I am missing?
Setting VerticalOptions to Fill at various elements has no effect.

In this picture, the black border shows that the FlexLayout works as expected and is only for display purposes:

The current state

Eventually, I would like to achieve the following effect, which is currently done in a hacky way using C# only:
The desired effect

The XAML code for the FlexLayout is as follows:

<FlexLayout Background="Gray"
            HeightRequest="100"
            JustifyContent="SpaceEvenly"
            AlignItems="Stretch">
<!-- Demo items for testing -->
<BindableLayout.ItemsSource>
    <x:Array Type="{x:Type x:String}">
        <x:String>1</x:String>
        <x:String>2</x:String>
        <x:String>3</x:String>
    </x:Array>
</BindableLayout.ItemsSource>
<BindableLayout.ItemTemplate>
    <DataTemplate>
        <!--Border to show that Flexlayout is behaving as expected-->
        <Border FlexLayout.Grow="1"
                Background="Transparent"
                Stroke="Black"
                StrokeThickness="2"
                StrokeShape="RoundRectangle 10">
            <!--This should occupy all the space available--> 
            <RadioButton Content="{Binding .}" HorizontalOptions="Center" FlexLayout.Grow="1">
                <RadioButton.ControlTemplate>
                    <ControlTemplate>
                        <Grid BackgroundColor="Cyan">
                            <Border Background="Orange"
                                    StrokeShape="RoundRectangle 10">
                            <Label Text="{TemplateBinding Content}"
                                   HorizontalOptions="Center"
                                   VerticalOptions="Center"/>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </RadioButton.ControlTemplate>
            </RadioButton>
        </Border>
    </DataTemplate>
</BindableLayout.ItemTemplate>

Edit: Because it was requested, this shows the "hacky way":
(ContentGrid is an empty Grid defined in XAML)

    internal void ReorderItems(IEnumerable<SelectionModel> items)
    {
        ContentGrid.Clear();
        ContentGrid.ColumnDefinitions.Clear();

        int counter = 0;
        foreach (var item in items)
        {
            ContentGrid.ColumnDefinitions.Add(new ColumnDefinition());
            Frame background = new()
            {
                HeightRequest = 44,
                HorizontalOptions = LayoutOptions.Fill,
                CornerRadius = 8,
                BorderColor = Colors.Transparent,
                Padding = 0,
                Style = Resources["NormalStyle"] as Style
            };
            //Selected item is a bindable property on the control
            if (SelectedItem is not null && item.Number == SelectedItem.Number)
                background.Style = Resources["SelectedStyle"] as Style;

            TapGestureRecognizer tapRecognizer = new()
            {
                Command = SelectionChangedCommand,
                CommandParameter = item,
            };
            background.GestureRecognizers.Add(tapRecognizer);
            
            Label numberLabel = new()
            {
                Text = item.Number.ToString(),
                TextColor = Color.FromArgb("#6D6D6D"),
                FontSize = 14,
                VerticalOptions = LayoutOptions.Center,
            };

            Image defaultImage = new()
            {
                Source = item.IsLocked ?
                    _lockImageSource : item.IsFinished ?
                    _finishedSource : item.IsStarted ?
                    _startedSource :
                    _notStartedSource,
                HeightRequest = 24,
                WidthRequest = 24,
                VerticalOptions = LayoutOptions.Center,
            };

            HorizontalStackLayout centerLayout =
            [
                numberLabel, defaultImage
            ];
            centerLayout.HorizontalOptions = LayoutOptions.Center;
            centerLayout.Spacing = 8;
            centerLayout.HeightRequest = 24;

            background.Content = centerLayout;

            ContentGrid.Add(background, counter, 0);

            counter++;
        }
    }
0

There are 0 best solutions below