Sinatr
Sinatr

Reputation: 21989

CheckBox.AutoCheck in wpf

What is the easiest alternative of making checkBox.AutoCheck= false in WPF? Specifically prevent CheckBox from changing IsChecked on click.

CheckBox should still react on clicks (Command and/or InputBindings), but shouldn't try to change its visual state on left click or Space key.

I can prevent bound property change by using Mode=OneWay, but this seems have no effect on visual state, CheckBox then become checked while my property is false, which makes me sad...

Here is an example of checkbox:

<!-- make this checkbox behave as if AutoCheck = false -->
<CheckBox IsChecked="{Binding IsChecked, Mode=OneWay}"
          Command="{Binding CommandLeftButtonOrSpace}">
    <CheckBox.InputBindings>
        <MouseBinding MouseAction="RightClick"
            Command="{Binding CommandRightButton}" />
    </CheckBox.InputBindings>
</CheckBox>

Upvotes: 4

Views: 1657

Answers (2)

Miral
Miral

Reputation: 13030

You can prevent it from toggling in the first place by subclassing the control (from another answer):

public class OneWayCheckBox : CheckBox
{
    private class CancelTwoWayMetadata : FrameworkPropertyMetadata
    {
        protected override void Merge(PropertyMetadata baseMetadata, DependencyProperty dp)
        {
            base.Merge(baseMetadata, dp);

            BindsTwoWayByDefault = false;
        }
    }

    static OneWayCheckBox()
    {
        // Remove BindsTwoWayByDefault
        IsCheckedProperty.OverrideMetadata(typeof(OneWayCheckBox), new CancelTwoWayMetadata());
    }

    protected override void OnToggle()
    {
        // Do nothing.
    }
}

This also switches the binding type of IsChecked so that you don't need to remember to put Mode=OneWay on it.

Upvotes: 3

Sinatr
Sinatr

Reputation: 21989

A simple attached behavior will do

public class CheckBoxBehavior
{
    public static bool GetDisableAutoCheck(DependencyObject obj) => (bool)obj.GetValue(DisableAutoCheckProperty);
    public static void SetDisableAutoCheck(DependencyObject obj, bool value) => obj.SetValue(DisableAutoCheckProperty, value);

    public static readonly DependencyProperty DisableAutoCheckProperty =
        DependencyProperty.RegisterAttached("DisableAutoCheck", typeof(bool),
        typeof(CheckBoxBehavior), new PropertyMetadata(false, (d, e) =>
        {
            var checkBox = d as CheckBox;
            if (checkBox == null)
                throw new ArgumentException("Only used with CheckBox");
            if ((bool)e.NewValue)
                checkBox.Click += DisableAutoCheck_Click;
            else
                checkBox.Click -= DisableAutoCheck_Click;
        }));

    private static void DisableAutoCheck_Click(object sender, RoutedEventArgs e) =>
        ((CheckBox)sender).IsChecked = !((CheckBox)sender).IsChecked;
}

Setting like this

<ComboBox local:CheckBoxBehavior.DisableAutoCheck="True" ... />

Upvotes: 3

Related Questions