Terra
Terra

Reputation: 120

.NET MAUI: Check checkbox when clicking on label

Is there a way in .NET MAUI to toggle the state of a checkbox when the label next to it is clicked? As an example:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.Views.Test"
             Title="Test">
    <HorizontalStackLayout>
        <CheckBox />
        <Label Text="Check this box" VerticalOptions="Center" />
    </HorizontalStackLayout>
</ContentPage>

Upvotes: 3

Views: 8781

Answers (6)

Guiorgy
Guiorgy

Reputation: 1734

You can use TapGestureRecognizer to manually toggle the checkbox when the label is tapped:

<Label Text="Click Me">
    <Label.GestureRecognizers>
        <TapGestureRecognizer Tapped="OnLabelClicked" />
    </Label.GestureRecognizers>
</Label>
private void OnLabelClicked(object sender, EventArgs e)
{
    CheckBox.IsChecked = !CheckBox.IsChecked;
}

To make it simpler, you could define a custom View:

<?xml version="1.0" encoding="utf-8" ?>
<HorizontalStackLayout xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="[NAMESPACE].CheckBoxLabeled"
    x:Name="this">
    
    <CheckBox
        x:Name="CheckBox"
        CheckedChanged="OnCheckChanged" />

    <Label
        Text="{Binding Source={x:Reference this}, Path=Text}"
        VerticalOptions="Center">

        <Label.GestureRecognizers>
            <TapGestureRecognizer Tapped="OnLabelClicked" />
        </Label.GestureRecognizers>

    </Label>

</HorizontalStackLayout>
using OnCheckedChanged = System.EventHandler<Microsoft.Maui.Controls.CheckedChangedEventArgs>;

namespace [NAMESPACE];

public partial class CheckBoxLabeled : HorizontalStackLayout
{
    public static readonly BindableProperty TextProperty = BindableProperty.Create(
        propertyName: nameof(Text),
        returnType: typeof(string),
        declaringType: typeof(CheckBoxLabeled),
        defaultValue: "",
        defaultBindingMode: BindingMode.OneWay);

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set { SetValue(TextProperty, value); }
    }

    public event OnCheckedChanged CheckedChanged;

    public bool IsChecked => CheckBox.IsChecked;

    public CheckBoxLabeled()
    {
        InitializeComponent();
    }

    private void OnLabelClicked(object sender, EventArgs e)
    {
        CheckBox.IsChecked = !CheckBox.IsChecked;
    }

    private void OnCheckChanged(object sender, CheckedChangedEventArgs e)
    {
        CheckedChanged?.Invoke(this, e);
    }
}

You can then use the view:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns:custom="clr-namespace:[NAMESPACE]">

<custom:CheckBoxLabeled Text="Click Me" CheckedChanged="OnClickMeCheckChanged" />

Note: Replace [NAMESPACE] with your project namespace!

Upvotes: 0

Goliatr
Goliatr

Reputation: 23

For anyone still interested, I just put both label and checkbox in a grid. Checkbox has to be last, so that it is drawn over the label. This way, click will be recognized directly by checkbox, no code behind needed. They both have to be same width, so they are drawn over the same space.

<Grid>
    <Label
        WidthRequest="160"
        VerticalTextAlignment="Center"
        HorizontalTextAlignment="Center"
        Text="Live Update" />
    <CheckBox
        WidthRequest="160"
        IsChecked="{Binding IsLiveUpdate}"
        VerticalOptions="Center" />
</Grid>

Upvotes: 2

Yuta Sola
Yuta Sola

Reputation: 11

//xaml

<HorizontalStackLayout>
   <HorizontalStackLayout.GestureRecognizers>
     <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
   </HorizontalStackLayout.GestureRecognizers>
   <CheckBox IsChecked="True" VerticalOptions="Center" />
     <Label Text="Hello" VerticalOptions="Center" />
</HorizontalStackLayout>

//xaml.cs

  private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
    {
        var layout = sender as Layout;
        var check = layout.FirstOrDefault(c => c.GetType() == typeof(CheckBox));

        if (check != null)
        {
            ((CheckBox)check).IsChecked = !((CheckBox)check).IsChecked;
        }
    }

Upvotes: 1

FreakyAli
FreakyAli

Reputation: 16459

Basically you need to do something like this:

             <ContentView
                Padding="10,20">
                <ContentView.GestureRecognizers>
                    <TapGestureRecognizer Command="{Binding SomeThingTappedCommand}" />
                </ContentView.GestureRecognizers>
                <StackLayout Orientation="Horizontal">
                    <Label
                        HorizontalOptions="StartAndExpand"
                        InputTransparent="True"
                        Text="Some Title"
                        VerticalTextAlignment="Center" />
                    <controls:ExtendedCheckBox
                        InputTransparent="True"
                        IsChecked="{Binding IsChecked}"
                        VerticalOptions="Center"
                        Color="{DynamicResource PrimaryColor}" />
                </StackLayout>
            </pan:PancakeView>

And then in your VM, all you need to do is:

 SomeThingTappedCommand = new Command(() => IsChecked = !IsChecked);

Where IsChecked is a notifiable property:

 private bool isChecked;
 public bool IsChecked
    {
        get => isChecked;
        set => SetProperty(ref isChecked, value);
    }

Upvotes: 2

Zack
Zack

Reputation: 1609

In the xamarin file:

<StackLayout Orientation="Horizontal">
        <CheckBox x:Name="myCheckBox"
              IsChecked="{Binding IsChecked,Mode=TwoWay}">
        </CheckBox>
        <Label VerticalTextAlignment="Center"  Text="Test">
            <Label.GestureRecognizers>
                <TapGestureRecognizer Tapped="Clicked"/>
            </Label.GestureRecognizers>
        </Label>
    </StackLayout>

And in code behind:

private void Clicked(object sender, EventArgs e)
    {
        myCheckBox.IsChecked = !myCheckBox.IsChecked;
    }

Upvotes: 2

Bas H
Bas H

Reputation: 2216

You can use it like this , a Label and a CheckBox.

Give the CheckBox a Name.

 <Label
            Text="Check this box"
            FontSize="32"
            HorizontalOptions="Center" >
            <Label.GestureRecognizers>
                <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"
                          NumberOfTapsRequired="1" />
            </Label.GestureRecognizers>
        </Label>
        
        <CheckBox x:Name="StackO" />

Then for the Label Tap

private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
    if (StackO.IsChecked )
       StackO.IsChecked = false;
    else
        StackO.IsChecked = true;
}

Upvotes: 0

Related Questions