Changing hit area of a Checkbox

2.1k views Asked by At

I'm trying to make a Multi select Combo box, everything seems to be working okay apart from selection, I'm using a custom template including a check box for the selection, I ignore all of the standard combo box selections.

Selecting rows works when the user clicks specifically on the check box or its text, however if the user clicks on the comboboxitem that is visible it closes the drop down and doesn't click the check box. I would like to be able to click anywhere within the combo box row to check the check box.

I've putting a transparent rectangle (Hot Pink for Debugging) above the check box that takes the input instead and sets the checked variable. The rectangle receives the input however it also still passes the click event on to the combo box and as a result selects the combo box row and closes the drop down.

Data Template

<DataTemplate x:Key="CheckBoxTemplate">
    <Grid>
        <Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="HotPink" IsHitTestVisible="True">
             <i:Interaction.Behaviors>
                 <behaviors:HitBoxBehaviour IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
             </i:Interaction.Behaviors>
         </Rectangle>
         <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Name}" Tag="{Binding Id}" HorizontalAlignment="Stretch" Height="25" FontSize="14"
                              VerticalAlignment="Stretch"/>
    </Grid>
</DataTemplate>

Behaviour

public class HitBoxBehaviour : Behavior<Rectangle>
{
    public bool IsChecked
    {
        get { return (bool)GetValue(IsCheckedProperty); }
        set { SetValue(IsCheckedProperty, value); }
    }

    public static readonly DependencyProperty IsCheckedProperty =
        DependencyProperty.Register("IsChecked", typeof(bool), typeof(HitBoxBehaviour),
        new PropertyMetadata(false, new PropertyChangedCallback(parameterChanged)));


    private static void parameterChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        this.AssociatedObject.MouseLeftButtonDown += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
    }

    void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        IsChecked = !IsChecked;
        e.Handled = true;
    }
}

Is there anyway to extend the hit box of the Check Box without passing the click event down to the combo box?

2

There are 2 answers

0
foson On BEST ANSWER

If you re-template the CheckBox and give it a transparent background, you'll be able to click anywhere to toggle its checkbox. No "hitbox" necessary.

<Style TargetType="CheckBox">
    <Setter Property="Background" Value="#FF448DCA"/>
    <Setter Property="Foreground" Value="#FF000000"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="Padding" Value="4,1,0,0"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FFA3AEB9" Offset="0"/>
                <GradientStop Color="#FF8399A9" Offset="0.375"/>
                <GradientStop Color="#FF718597" Offset="0.375"/>
                <GradientStop Color="#FF617584" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="CheckBox">
                <!-- Added Background here -->
                <Grid Background="Transparent">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="16"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
1
shibbybird On

This works for me:

XAML

<Border x:Name="CheckBorder" Width="100" Height="30" Background="Black" MouseLeftButtonDown="CheckBorder_MouseLeftButtonDown">
      <CheckBox x:Name="CheckBox"></CheckBox>
</Border>

CS

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