首页 文章

WPF绑定复选框IsChecked到其他复选框(IsChecked ||!IsEnabled)

提问于
浏览
6

我有一个选择'全部'复选框,我想绑定到其他复选框的(IsChecked ||!IsEnabled) .

  • 选中“全部”选中所有已启用的复选框 .

  • 取消选中“全部”取消选中所有复选框 .

  • 手动检查每个已启用的复选框将选中“全部” .

  • 当选中所有已启用的复选框和“全部”并且用户取消选中任何复选框时,“全部”会自动取消选中 .

我是WPF Databinding的新手 . 我想也许我只是点击“全部”来设置其他复选框 . 但我不知道如何绑定到多个源的两个属性 . 当我点击“全部”并手动取消选中另一个复选框时,“全部”需要取消选中 .

2 回答

  • 12

    这是使用转换器在Xaml中执行此操作的方法 . 这假设您的所有CheckBox都直接作为Xaml中的控件添加(它不是非常动态,不适用于DataTemplate等) . 首先,我们创建三个CheckBoxes(CheckBox1,CheckBox2,CheckBox3),在检查CheckAllCheckBox时将检查/取消选中 . 它也会反向运作 .

    Update
    最后一部分(忽略禁用的CheckBox)在这里有点问题,我看到了更好的方法 . 我们存储Convert的值,并在ConvertBack中重用它们用于禁用的CheckBox . 这样做,我们还应该为CheckAllConverter添加x:Shared = "False"属性,因为每个使用它的MultiBinding都需要一个新实例(在这种情况下不太可能但仍然......)

    <Window.Resources>
        <local:CheckAllConverter x:Key="CheckAllConverter" x:Shared="False"/>
    </Window.Resources>
    <StackPanel>
        <CheckBox Content="Check All"
                  Name="CheckAllCheckBox">
            <CheckBox.IsChecked>
                <MultiBinding Converter="{StaticResource CheckAllConverter}">
                    <Binding ElementName="CheckBox1" Path="IsChecked" />
                    <Binding ElementName="CheckBox1" Path="IsEnabled" Mode="OneWay"/>
                    <Binding ElementName="CheckBox2" Path="IsChecked" />
                    <Binding ElementName="CheckBox2" Path="IsEnabled" Mode="OneWay"/>
                    <Binding ElementName="CheckBox3" Path="IsChecked" />
                    <Binding ElementName="CheckBox3" Path="IsEnabled" Mode="OneWay"/>
                </MultiBinding>
            </CheckBox.IsChecked>
        </CheckBox>
        <CheckBox Content="CheckBox 1"
                  Name="CheckBox1"/>
        <CheckBox Content="CheckBox 2"
                  Name="CheckBox2"/>
        <CheckBox Content="CheckBox 3"
                  Name="CheckBox3"/>
    </StackPanel>
    

    CheckAll转换器

    public class CheckAllConverter : IMultiValueConverter
    {
        private object[] convertValues = null;
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            convertValues = new object[values.Length];
            for(int i = 0; i < values.Length; i++)
            {
                convertValues[i] = values[i];
            }
    
            for (int i = 0; i < values.Length; i += 2)
            {
                bool isChecked = (bool)values[i];
                bool isEnabled = (bool)values[i + 1];
                if (isEnabled == false)
                {
                    continue;
                }
                if (isChecked == false)
                {
                    return false;
                }
            }
            return true;
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            object[] values = new object[targetTypes.Length];
            for (int i = 0; i < values.Length; i += 2)
            {
                if (convertValues != null && (bool)convertValues[i + 1] == false)
                {
                    values[i] = convertValues[i];
                }
                else
                {
                    values[i] = value;
                }
                // IsEnabled is OneWay and won't care about this value
                values[i + 1] = null;
            }
            return values;
        }
    }
    
  • 1

    我将使用MVVM设计模式在View类后面创建一个ViewModel:http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

    然后在您的ViewModel(必须实现INotifyPropertyChanged)上,您可以拥有多个 bool 属性,每个CheckBox一个属性,另外一个用于所有属性:

    public bool IsChecked1
    {
        get
        {
             return isChecked1;
        }
        set
        {
             if (isChecked1 != value)
             {
                 isChecked1 = value;
                 RaisePropertyChanged("IsChecked1");
                 RaisePropertyChanged("AreAllChecked");
             }
        }
    }
    
    // And so on
    
    public bool AreAllChecked
    {
        get
        {
            return IsChecked1 && IsChecked2; // etc.
        }   
        set
        {
            if (AreAllChecked != value)
            {
                IsChecked1 = value;
                IsChecked2 = value;
                // etc.
            }
        }
    }
    

相关问题