Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TriState Checkbox - how to change the order of the states

Tags:

checkbox

wpf

I have a CheckBox in my application that is using the TriState mode. The normal behavior for this mode seems to be cycling between null, false, true.

I'd like to change this behavior so that it cycles between null, true, false.

What's the best way to do this?

I've tried adding a click handler similar to this:

void cb_Click(object sender, RoutedEventArgs e)
{
    if (((CheckBox)e.Source).IsChecked.HasValue == false)
    {
        ((CheckBox)e.Source).IsChecked = true;
        return;
    }

    if (((CheckBox)e.Source).IsChecked == true)
    {
        ((CheckBox)e.Source).IsChecked = false;
        return;
    }

    if (((CheckBox)e.Source).IsChecked == false)
    {
        ((CheckBox)e.Source).IsChecked = null;
        return;
    }

}

But this seems to disable the checkbox entirely. I'm pretty sure I'm missing something that should be obvious.

like image 767
Jason Avatar asked Aug 27 '09 21:08

Jason


2 Answers

Only for completeness here additionally the solution for Windows-Forms. We have to override the OnClick method, overriding OnStateChanged results in display bug (and stackoverflow if done incorrectly).

/// <summary>
/// A <see cref="System.Windows.Forms.CheckBox"/> with the ability to reverse the checkstate order.
/// </summary>
/// <seealso cref="System.Windows.Forms.CheckBox" />
public class CheckBoxReversible : CheckBox
{
    private bool FInvertCheckStateOrder;

    /// <summary>
    /// Gets or sets a value indicating whether to invert the check state order from [Indeterminate->Unchecked->Checked] to [Indeterminate->Checked->Unchecked].
    /// </summary>
    /// <value>
    ///   <c>true</c> to invert the check state order; otherwise, <c>false</c>.
    /// </value>
    public bool InvertCheckStateOrder
    {
        get { return FInvertCheckStateOrder; }
        set { FInvertCheckStateOrder = value; }
    }

    /// <summary>
    /// Löst das <see cref="E:System.Windows.Forms.Control.Click" />-Ereignis aus.
    /// </summary>
    /// <param name="e">Eine Instanz der <see cref="T:System.EventArgs" />-Klasse, die die Ereignisdaten enthält.</param>
    protected override void OnClick(EventArgs e)
    {
        if (this.InvertCheckStateOrder)
        {
            if (this.CheckState == CheckState.Indeterminate)
                this.CheckState = CheckState.Checked;
            else
                if (this.CheckState == CheckState.Checked)
                    this.CheckState = CheckState.Unchecked;
                else
                    if (this.CheckState == CheckState.Unchecked)
                        this.CheckState = this.ThreeState ? CheckState.Indeterminate : CheckState.Checked;
        }
        else
            base.OnClick(e);
    }
}
like image 149
casiosmu Avatar answered Oct 19 '22 21:10

casiosmu


I guess the event handler and the default behavior are just cancelling each other's effects, so the checkbox seems disabled...

Actually I recently had to do the same thing. I had to inherit from CheckBox and override OnToggle :

public class MyCheckBox : CheckBox
{


    public bool InvertCheckStateOrder
    {
        get { return (bool)GetValue(InvertCheckStateOrderProperty); }
        set { SetValue(InvertCheckStateOrderProperty, value); }
    }

    // Using a DependencyProperty as the backing store for InvertCheckStateOrder.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty InvertCheckStateOrderProperty =
        DependencyProperty.Register("InvertCheckStateOrder", typeof(bool), typeof(MyCheckBox), new UIPropertyMetadata(false));

    protected override void OnToggle()
    {
        if (this.InvertCheckStateOrder)
        {
            if (this.IsChecked == true)
            {
                this.IsChecked = false;
            }
            else if (this.IsChecked == false)
            {
                this.IsChecked = this.IsThreeState ? null : (bool?)true;
            }
            else
            {
                this.IsChecked = true;
            }
        }
        else
        {
            base.OnToggle();
        }
    }
}
like image 28
Thomas Levesque Avatar answered Oct 19 '22 20:10

Thomas Levesque