0

MultiBinding

我想要什么:单击任一复选框应切换所有其他复选框。

问题:点击A不变B,点击B不变AResult作品。

问题:我将如何修复它,同时仍在使用MultiBinding

PS:这是解决更复杂问题的尝试,请在提供将所有复选框绑定到单个属性之前参考它。


下面是一个mcve

xml:

<StackPanel>
    <CheckBox Content="A" IsChecked="{Binding A}" />
    <CheckBox Content="B" IsChecked="{Binding B}" />
    <CheckBox Content="Result">
        <CheckBox.IsChecked>
            <MultiBinding Converter="{local:MultiBindingConverter}">
                <Binding Path="A" />
                <Binding Path="B" />
            </MultiBinding>
        </CheckBox.IsChecked>
    </CheckBox>
</StackPanel>

CS:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}

视图模型:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string property = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));

    bool _a;
    public bool A
    {
        get { return _a; }
        set { _a = value; OnPropertyChanged(); }
    }

    bool _b;
    public bool B
    {
        get { return _b; }
        set { _b = value; OnPropertyChanged(); }
    }
}

转换器:

public class MultiBindingConverter : MarkupExtension, IMultiValueConverter
{
    public MultiBindingConverter() { }

    public override object ProvideValue(IServiceProvider serviceProvider) => this;

    object[] _old;

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        // first time init
        if (_old == null)
            _old = values.ToArray();
        // find if any value is changed and return value
        for (int i = 0; i < values.Length; i++)
            if (values[i] != _old[i])
            {
                _old = values.ToArray();
                return values[i];
            }
        // if no changes return first value
        return values[0];
    }


    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
        Enumerable.Repeat(value, targetTypes.Length).ToArray();
}
4

2 回答 2

0

原因很简单,ConvertBack()当您单击CheckBox A时,该方法将永远不会被调用。

考虑以下推理:

Checkbox A检查

<Binding />调用 Property-Setter A

属性设置器A​​ 被调用。

属性设置器A​​ 调用OnPropertyChanged("A").

PropertyChanged-Event 由<MultiBinding />ResultCheckBox 接收

正在调用属性获取器AB (仍然未更改)。

MultiBindingConverter.Convert()方法被绑定调用。

<MultiBinding />更新视图中的CheckBox 结果 IsChecked状态。


更改的处理是在不接触CheckBoxB 的情况下完成的,只调用属性B的 getter 。


如果你有一个MultiBindingon all CheckBoxes,那么所有合适的 setter 都会被调用。但是,如果每个CheckBox.

这也是为什么改变这样的东西应该 - 最好 - 如果可能的话在 ViewModel 中完成的原因,因为所有这些 Bindings 和 Converters 使它有点难以跟踪。

于 2017-08-08T14:17:06.640 回答
0

我认为你的转换器应该是这样的

public class MultiBindingConverter : MarkupExtension, IMultiValueConverter
    {
        public MultiBindingConverter() { }

        public override object ProvideValue(IServiceProvider serviceProvider) => this;

        object[] _old;

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return ((bool)values[0] /*A */) || ((bool)values[1]/* B */);
        }


        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
           return new object[] { (bool)value, (bool)value};
        }
}

接着

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string property = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));

    bool _a;
    public bool A
    {
        get { return _a || _b; }
        set {
              if (_a == value) return;
              _a = value; 
              OnPropertyChanged("A");
              OnPropertyChanged("B");
            }
    }

    bool _b;
    public bool B
    {
        get { return _b || _a; }
        set {
              if (_b == value) return;
              _b = value; 
              OnPropertyChanged("B");
              OnPropertyChanged("A");
            }
    }
}
于 2016-03-17T15:20:19.853 回答