Forcing a tri-state checkbox to not move to indeterminate state

XAML:

<CheckBox IsThreeState="True" IsChecked="{x:Null}" Click="CheckBox_Clicked" />

Code-behind:

private void CheckBox_Clicked(object sender, RoutedEventArgs e)
  {
     var cb = e.Source as CheckBox;
     if (!cb.IsChecked.HasValue) 
        cb.IsChecked = false;
  }

If you don't like the code-behind solution, then you could sub-class your own control like in the solution for this question.


It's much easier if you use Binding with your CheckBox.

XAML:

<Window x:Class="WpfApplication39Checkbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <CheckBox Content="CheckBox" HorizontalAlignment="Left" Margin="128,95,0,0" VerticalAlignment="Top" IsThreeState="False" IsChecked="{Binding CheckState}"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="46,241,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="139,241,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="235,241,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2"/>
    </Grid>
</Window>

Code-behind:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApplication39Checkbox
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private bool? checkState;

        public bool? CheckState
        {
            get { return checkState; }
            set
            {
                checkState = value;
                OnPropertyChanged("CheckState");
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            CheckState = false;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            CheckState = true;
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            CheckState = null;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

You see the point? You set the CheckBox to IsThreeState="False" but set the third state from CodeBehind and the CheckBox behaves as expected.

Tags:

Wpf

Checkbox