【问题标题】:WPF Radiobutton (two) (binding to boolean value)WPF Radiobutton(二)(绑定到布尔值)
【发布时间】:2011-03-22 15:22:34
【问题描述】:

我有一个带有复选框的布尔类型属性。

我想将其更改为绑定在相同属性上的两个单选按钮,呈现值 true/false。

如何做到这一点?

【问题讨论】:

    标签: wpf binding radio-button boolean


    【解决方案1】:

    您可以使用一个值转换器来恢复布尔值:

    使用该转换器,将一个 Checkbox.IsChecked-property 绑定到没有转换器的布尔值,并将一个 CheckBox.IsChecked-property 与转换器绑定。这应该可以解决问题。

    这里是这种转换器的代码。我从here 复制了它并添加了一些代码行。在那里你会找到更多的信息。

    public class BoolToOppositeBoolConverter : IValueConverter {
        public object Convert(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture) {
            if (targetType != typeof(bool)) {
                throw new InvalidOperationException("The target must be a boolean");
            }
            if (null == value) {
                return null;
            }
                        return !(bool)value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture) {
            if (targetType != typeof(bool)) {
                throw new InvalidOperationException("The target must be a boolean");
            }
            if (null == value) {
                return null;
            }
            return !(bool)value;
        }
    } 
    

    要使用它,请在资源部分中声明它。

     <local:BoolToOppositeBoolConverter x:Key="BoolToOppositeBoolConverter_ValueConverter"/>
    

    并且在绑定中使用它作为静态资源:

    <CheckBox IsChecked="{Binding YourProperty}" />
    <CheckBox IsChecked="{Binding YourProperty,Converter={StaticResource BoolToOppositeBoolConverter_ValueConverter}}" />
    

    请注意,转换器只是一个简单的例子。如果您想在生产代码中使用它,请巧妙地实现它。我还没有测试过。如果它不起作用,请发表评论。

    【讨论】:

    • 谢谢!我使用过 Ragunathan 解决方案,但两者都很好用。特别感谢您的解释和投入的时间。慢慢地我在 WPF 中挖掘我的方式......
    【解决方案2】:
    <RadioButton GroupName="Group1" 
                 IsChecked="{Binding PropertyValue}" Content="Yes" />
    <RadioButton GroupName="Group1"  Content="No" 
                 IsChecked="{Binding PropertyValue, 
                             Converter={StaticResource BoolInverterConverter}}" />
    
    public class BoolInverterConverter : IValueConverter
    {
        #region IValueConverter Members
    
        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            if (value is bool)
            {
                return !(bool)value;
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, 
            System.Globalization.CultureInfo culture)
        {
            if (value is bool)
            {
                return !(bool)value;
            }
            return value;
        }
    
        #endregion
    }
    

    【讨论】:

    • 出于某种原因,我必须使用两个不同的 GroupName。否则,可以将 ViewModel 中的布尔值设置为 true,但永远不会重置为 false(即使单选按钮看起来正常)
    • 您好,您忘记用“/”关闭第二个单选按钮了。
    • @Ragunathan 我收到一个错误:“资源 'BoolInverterConverter' 无法解析”。不知道如何解决这个问题:有什么想法吗?
    • @BKSpureon:你只需要添加一个资源部分
    • 我把它放在子窗口中。当我第一次打开子窗口时,它很好。当我第二次关闭并打开子窗口时,由于转换器执行了无数次,因此出现堆栈溢出异常。
    【解决方案3】:

    如果您将两个单选按钮的 GroupName 属性设置为相同的值,则无需转换器即可实现此目的(因此当时只能检查一个)。然后,将一个单选按钮的 IsChecked 设置为“True”,并将另一个单选按钮的 IsChecked 绑定到您的布尔值。切换单选按钮会更改布尔值,但是,将布尔值更改为 False 不会检查其他单选按钮。

    谢谢, 弗拉德

    【讨论】:

    • 如果您多次显示对话框,此方法会产生间歇性绑定副作用。我可以通过在关闭对话框之前清理 Data Context 属性来解决它,所以对我来说它看起来像是一个框架问题。无论如何,我想出了一个更好的解决方案,它支持布尔和枚举,并且无论 GroupName 属性是否设置都可以正常工作。
    【解决方案4】:

    下面是如何通过示例代码将单选按钮绑定到任何类型(枚举、布尔值、字符串、整数等)的解决方案:

    http://www.codeproject.com/Tips/720497/Binding-Radio-Buttons-to-a-Single-Property

    【讨论】:

      【解决方案5】:

      标准绑定方法有一个不幸的副作用,即在加载 UI 时将绑定设置器触发为“未选择”。因此,如果您有代码来处理用户在 bool 的 setter 中的点击,即使您已将 setter 绑定到“true”布尔值,它也会做一些奇怪的事情,例如将 setter 设置为“false”。

      我使用专门用于单选按钮的转换器解决了这个问题:

      public class BoolRadioConverter : IValueConverter
      {
          public bool Inverse { get; set; }
      
          public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
          {
              bool boolValue = (bool) value;
      
              return this.Inverse ? !boolValue : boolValue;
          }
      
          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
          {
              bool boolValue = (bool)value;
      
              if (!boolValue)
              {
                  // We only care when the user clicks a radio button to select it.
                  return null;
              }
      
              return !this.Inverse;
          }
      }
      

      在您的资源中:

      <converters:BoolRadioConverter x:Key="BoolRadioConverter" />
      <converters:BoolRadioConverter x:Key="InverseBoolRadioConverter" Inverse="True" />
      

      在您的 xaml 中:

      <RadioButton
          Content="True option"
          GroupName="radioGroup1"
          IsChecked="{Binding MyProperty,
                              Converter={StaticResource BoolRadioConverter}}" />
      <RadioButton
          Content="False option"
          GroupName="radioGroup2"
          IsChecked="{Binding MyProperty,
                              Converter={StaticResource InverseBoolRadioConverter}}" />
      

      【讨论】:

      • 太棒了!对我的问题按预期工作。复制到我的博客以供将来参考
      • 如果我称它为InverseBoolRadioConverter,我可以忽略 Inverse 变量,并返回 true,因为我总是将它用作单选按钮的转换器。
      • 我发现您的代码最适用于可为空的布尔值,但您可以调整转换器中的 if 条件以处理不可为空: if (!boolValue && Nullable.GetUnderlyingType(targetType) != null )
      • 谢谢!面临同样的问题,很高兴我找到了您的解决方案
      • 当我认识到单选按钮需要位于不同的组时,对我来说效果很好。
      【解决方案6】:

      ragunathananswer 的简化版。

      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) =>
          Convert(value);
      
      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) =>
          Convert(value);
      
      private object Convert(object value) => 
          value is bool ? !(bool)value : value;
      

      【讨论】:

        【解决方案7】:

        如果您希望 bool 可以为空(对于没有默认值/选中的单选按钮),请稍微升级 RandomEngy 的答案

        public class BoolRadioConverter : IValueConverter
        {
            public bool Inverse { get; set; }
        
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                bool? boolValue = (bool?)value;
        
                return this.Inverse ? !boolValue : boolValue;
            }
        
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                bool? boolValue = (bool?)value;
        
                if (boolValue != null && (bool)!boolValue)
                {
                    // We only care when the user clicks a radio button to select it.
                    return null;
                }
        
                return !this.Inverse;
            }
        }
        

        其余的和他的回答一样。

        【讨论】:

          【解决方案8】:

          当使用 MVVMLightDataContextXAML 中设置为:

          DataContext="{Binding <Your ViewModel property name>, Source={StaticResource Locator}}" 
          

          BoolInverterConverter 导致 Stack Overflow 第二次打开窗口。

          解决方法是从 XAML 中删除 DataContext,并在 InitializeComponent() 之后的窗口构造函数中的代码中执行此操作:

          DataContext = ServiceLocator.Current.GetInstance<Your View Model class>();
          

          经过一些测试,这还不够 - 单击单选按钮时可能会随机弹出 Stack Overflow 错误。对我有用的解决方案 - 而不是转换器,而是为组中的其他单选按钮使用另一个属性:

          public bool Is9to1 { get; set; }
          public bool Is1to9 { get { return !Is9to1; } set { Is9to1 = !value; } } 
          

          在 XAML 中:

             <RadioButton GroupName="Is9to1" IsChecked="{Binding Is1to9}"/>
             <RadioButton GroupName="Is9to1" IsChecked="{Binding Is9to1}"/>
          

          【讨论】:

          • 这里有同样的问题。我对 WPF 很陌生,所以我停止研究为什么会发生这种情况。最后,我在 XAML 中使用带有CommandParameter 的自定义转换器来避免 SOE。例如。 Yes 选项与CommandParameter=1No 选项与CommandParameter=2
          猜你喜欢
          • 2021-04-02
          • 2016-09-26
          • 2017-12-23
          • 2015-04-07
          • 1970-01-01
          • 1970-01-01
          • 2014-10-17
          • 1970-01-01
          • 2015-10-04
          相关资源
          最近更新 更多