WPF Bind Checkbox IsChecked для других флажков (IsChecked ||! IsEnabled) - PullRequest
6 голосов
/ 14 декабря 2010

У меня есть флажок «Все», который я бы хотел привязать к (IsChecked ||! IsEnabled) других флажков.

  • При установке флажка «Все» отмечены все включенные флажки.

  • При снятии флажка «Все» снимаются все флажки.

  • Вручную проверяя каждый включенный флажок, отметим «Все».

  • Когда все включенные флажки и «Все» установлены и пользователь снимает флажок, «Все» автоматически снимает флажок.

Я новичок в привязке данных WPF.Я думал, может быть, я просто обработать щелчок «Все», чтобы установить другие флажки.Но я не знаю, как связать оба свойства нескольких источников.Когда я нажимаю «Все» и вручную сниму другой флажок, «Все» необходимо снять.

Ответы [ 2 ]

12 голосов
/ 14 декабря 2010

Вот способ сделать это в Xaml с помощью Конвертеров.Это предполагает, что все ваши CheckBox добавляются непосредственно как элементы управления в Xaml (это не очень динамично, не будет работать для DataTemplate и т. Д.).Сначала мы создаем три CheckBoxes (CheckBox1, CheckBox2, CheckBox3), которые будут проверяться / не проверяться при проверке CheckAllCheckBox.Он также будет работать в обратном порядке.

Обновление
Последняя часть (игнорируйте отключенный CheckBox) была здесь небольшой проблемой, и я не без ума от этого решения, но могуне вижу лучшего пути.Мы сохраняем значения из Convert и повторно используем их в ConvertBack для отключенных флажков.Для этого мы также должны добавить атрибут x: Shared = "False" для CheckAllConverter, поскольку для каждого 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 голос
/ 14 декабря 2010

Я бы создал ViewModel за вашим классом View, используя шаблон проектирования MVVM: 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.
        }
    }
}  
...