首页 > 解决方案 > 当另一个切换为真时如何将切换更改为假

问题描述

当我尝试关闭一个开关并打开另一个开关的逻辑时,我得到了堆栈溢出。

我有 2 个开关。它们都在 VM 中侦听 2 个不同的属性(IsAddAppleEnabledIsAddOrangeEnabled)。

我希望它什么时候IsAddAppledEnabled是真的,什么时候IsAddOrangeEnabled是假的……反之亦然。

我尝试在设置器中执行此操作,但最终进入循环并获得 stackoverflow 异常

    private bool isAddAppledEnabled= false;
    public bool isAddAppledEnabled
    {
        get { return isAddReplicateToggleChecked; }
        set
        {
            isAddAppledEnabled= value;
            isAddOrangeEnabled= !value;
            OnPropertyChanged(nameof(IsAddAppledEnabled));
        }
    }

    private bool isAddOrangeEnabled= false;
    public bool IsAddOrangeEnabled
    {
        get { return isAddOrangeEnabled; }
        set
        {
            isAddOrangeEnabled= value;
            isAddAppledEnabled= !value;
            OnPropertyChanged(nameof(IsAddOrangeEnabled));
        }
    }

标签: c#wpfxaml

解决方案


选项 A(最小进近变化)

private bool _isAddAppledEnabled = false;
public bool IsAddAppledEnabled
{
  get { return _isAddAppledEnabled; }
  set
  {
    if (_isAddAppledEnabled == value)
      return;

    _isAddAppledEnabled = value;
    IsAddOrangeEnabled = !value;
    OnPropertyChanged(nameof(IsAddAppledEnabled));
  }
}

private bool _isAddOrangeEnabled = false;
public bool IsAddOrangeEnabled
{
  get { return _isAddOrangeEnabled; }
  set
  {
    if (_isAddOrangeEnabled == value)
      return;

    _isAddOrangeEnabled = value;
    IsAddAppledEnabled = !value;
    OnPropertyChanged(nameof(IsAddOrangeEnabled));
  }
}

选项 B(布尔反转转换器):您可以在视图模型中使用单个属性并利用转换器,以便 xaml 可以根据状态做出不同的反应。

一个例子是简单地使用一个 bool (就像你一样)并应用一个反转转换器

  public class InvertedBooleanConverter : MarkupExtension, IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

      if (value == null || (bool)value == false)
        return true;
      else
        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      if (value == null || (bool)value == false)
        return true;
      else
        return false;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
      return this;
    }
  }

用法:

  <Button IsEnabled="{Binding IsAddAppledEnabled}">
  <Button IsEnabled="{Binding IsAddAppledEnabled, Converter={yourNamespace:InvertedBooleanConverter}}">

选项 C(枚举转换器):如果您最终获得额外的互斥状态,另一个可能效果更好的选项是使用 enum

转换器

  public class EnumToBooleanConverter : MarkupExtension, IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      return value.Equals(parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      return value.Equals(true) ? parameter : Binding.DoNothing;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
      return this;
    }
  }

视图模型:

public enum Fruits { Apple, Orange, Pear, Grape }

private Fruits _selectedFruit;
public Fruits SelectedFruit
{
  get { return _selectedFruit; }
  set
  {
    _selectedFruit = value;
    OnPropertyChanged(nameof(SelectedFruit));
  }
}

Xaml 用法:

<RadioButton Content="Apple" IsChecked="{Binding Path=SelectedFruit, Mode=TwoWay, Converter={yourNamespace:EnumToBooleanConverter}, ConverterParameter={x:Static yourNamespace:Fruits.Apple}}"/>
<RadioButton Content="Orange" IsChecked="{Binding Path=SelectedFruit, Mode=TwoWay, Converter={yourNamespace:EnumToBooleanConverter}, ConverterParameter={x:Static yourNamespace:Fruits.Orange}}"/>
<RadioButton Content="Pear" IsChecked="{Binding Path=SelectedFruit, Mode=TwoWay, Converter={yourNamespace:EnumToBooleanConverter}, ConverterParameter={x:Static yourNamespace:Fruits.Pear}}"/>
<RadioButton Content="Grape" IsChecked="{Binding Path=SelectedFruit, Mode=TwoWay, Converter={yourNamespace:EnumToBooleanConverter}, ConverterParameter={x:Static yourNamespace:Fruits.Grape}}"/>

推荐阅读