WPF Radiobutton(二)(绑定到布尔值)

Posted

技术标签:

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

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

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

如何做到这一点?

【问题讨论】:

【参考方案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】:

ragunathan 的answer 的简化版。

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

以上是关于WPF Radiobutton(二)(绑定到布尔值)的主要内容,如果未能解决你的问题,请参考以下文章

WPF绑定Radiobutton到enum

WPF + MVVM + RadioButton:使用单个属性处理绑定

WPF MVVM从入门到精通6:RadioButton等一对多控件的绑定

使用一组 RadioButton 作为选择器

wpf中datagrid选择改变事件中怎样绑定RadioButton的数据

WPF:多重绑定不使用 OnPropertyChanged 更新?