Принудительное переключение трех состояний, чтобы не переходить в неопределенное состояние - PullRequest
9 голосов
/ 13 октября 2010

Я работаю в WPF, и у меня есть интересное требование. Мне нужно, чтобы мои флажки были ThreeState, поэтому, если выбраны только некоторые из дочерних элементов, они отображаются как неопределенные. Но когда пользователь нажимает на него, я хочу, чтобы он выбрал либо true, либо false.

Вот история для представления моих требований:

item - indeterminate  
    subItem - checked  
    subItem - unchecked  
    subItem - checked  

Когда пользователь нажимает item, флажок должен чередоваться между установленным и непроверенным. Пользователь никогда не должен иметь возможность выбирать «неопределенный» в качестве состояния. Это возможно?

Ответы [ 2 ]

17 голосов
/ 13 октября 2010

XAML:

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

Код-за:

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

Если вам не нравится решение с выделенным кодом, тогда вы можете подразделить свой собственный контроль, как в решении для этого вопроса.

14 голосов
/ 29 апреля 2014

Гораздо проще, если вы используете Binding с 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>

Код-за:

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));
        }
    }
}

Вы видите смысл? Вы устанавливаете CheckBox в IsThreeState = "False", но устанавливаете третье состояние из CodeBehind, и CheckBox ведет себя как ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...