WPF 单选按钮(二)(绑定到布尔值)

发布于 2024-09-11 22:41:02 字数 86 浏览 3 评论 0原文

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

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

那怎么办呢?

I have a property of type boolean presented with checkbox.

I want to change that to two radiobuttons that bind on the same property presenting the value true/false.

How can that be done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

断肠人 2024-09-18 22:41:02
<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
}
<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
}
情仇皆在手 2024-09-18 22:41:02

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

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

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}}" />

The standard binding approach has the unfortunate side effect of firing the binding setter as "unselected" whenever the UI is loaded. So if you've got code to handle the user's clicks in the setter for your bool, it will do some weird stuff like fire the setter to "false" even though you've bound it to a "true" bool.

I got around this with a converter used specifically for radio buttons:

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;
    }
}

In your resources:

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

In your 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}}" />
谁人与我共长歌 2024-09-18 22:41:02

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

使用该转换器,将一个 Checkbox.IsChecked 属性绑定到不带转换器的布尔值,并将一个 CheckBox.IsChecked 属性绑定到带转换器的布尔值。这应该可以解决问题。

这是此类转换器的代码。我从此处复制了它并添加了一些代码行。在那里您将找到有关的更多信息。

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}}" />

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

You can use a value-converter that reverts the boolean value:

With that converter, bind one Checkbox.IsChecked-property to the boolean value without the converter and one CheckBox.IsChecked-property with the converter. This should do the trick.

Here the code for such a converter. I have copied it from here and added some lines of code. There you will find more information about.

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;
    }
} 

To use it, declare it in the resource-section.

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

And the use it in the binding as a static resource:

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

Please note, the converter is only a simple example. Implement it neatly if you want to use it in productive code. I have not tested it. Make a comment if its not working.

你怎么这么可爱啊 2024-09-18 22:41:02

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

谢谢,
弗拉德

You can achieve this without a converter if you set the GroupName property of two radio button to the same value (so only one can be checked at the time). Then, set IsChecked of one radio button to "True", and bind IsChecked of another to your Boolean. Switching radio buttons will change the Boolean value, however, changing the Boolean value to False will not check the other radio button.

Thanks,
Vlad

你是我的挚爱i 2024-09-18 22:41:02

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

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

Here is the solution on how to bind radio buttons to any type (enumeration, Boolean, string, integer, etc.) with the sample code:

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

蓝眼睛不忧郁 2024-09-18 22:41:02

当使用 MVVMLight 且在 XAML 中将 DataContext 设置为:

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

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

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

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

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

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}"/>

When using MVVMLight and DataContext is set in XAML as:

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

BoolInverterConverter causes Stack Overflow second time the window gets opened.

The work around is to remove DataContext from XAML and do it in code in window constructor after InitializeComponent():

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

After some testing it was not enough - Stack Overflow error could pop up randomly when clicking on radio button. The solution which worked for me - instead of the converter use another property for other radio button in a group:

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

in XAML:

   <RadioButton GroupName="Is9to1" IsChecked="{Binding Is1to9}"/>
   <RadioButton GroupName="Is9to1" IsChecked="{Binding Is9to1}"/>
于我来说 2024-09-18 22:41:02

ragunathan的简化版本回答

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;

Simplified version of ragunathan's 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;
长亭外,古道边 2024-09-18 22:41:02

如果您希望 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;
    }
}

,其余部分与他的答案相同。

Little upgrade of RandomEngy's answer if you want your bool nullable (for no default value/Checked Radiobutton)

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;
    }
}

and the rest is the same as his answer.

最近可好 2024-09-18 22:41:02

Mr-RandomQC 的答案一切正常。但是当我单击同一组中的另一个收音机时。然后对面的单选按钮将在单选按钮周围显示一个红色框。

我从他的答案中稍微更改了代码,以返回 Binding.DoNothing 而不是像这样返回 null

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)
        {
            // Return Binding.DoNothing instead of Return null
            return Binding.DoNothing;
        }

        return !this.Inverse;
    }
}

From The answer of Mr-RandomQC everything works fine. But when I click another radio in the same group. Then the opposite radio will show a Red box around the radio button.

I changed the code a little bit from his answer to return Binding.DoNothing instead of return null like this.

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)
        {
            // Return Binding.DoNothing instead of Return null
            return Binding.DoNothing;
        }

        return !this.Inverse;
    }
}
风流物 2024-09-18 22:41:02

迟到的答案,但我们多年来一直这样做,首先是 WPF,现在是 WinUI 3

<StackPanel>

<TextBlock Text="Payment terms" />

<RadioButton
    x:Name="rdo_on_account"
    Content="Account"
    GroupName="account"
    IsChecked="{x:Bind ViewModel.IsOnAccount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

<RadioButton
    Content="Cash"
    GroupName="account"
    IsChecked="{Binding ElementName=rdo_on_account, Path=IsChecked, Converter={StaticResource BoolInvert}}" />
    
</StackPanel>



public class BoolInvert : IValueConverter
{
// convert the value to the destination format
public object Convert(object value, Type targetType, object parameter, string language)
{
    if (value is bool)
    {
        if ((bool)value == true)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    //not a bool
    return value;
}

// convert from the destination format to the source format
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
    return value;
}
}

Late answer but weve been doing it like this for years, firstly with WPF now with WinUI 3

<StackPanel>

<TextBlock Text="Payment terms" />

<RadioButton
    x:Name="rdo_on_account"
    Content="Account"
    GroupName="account"
    IsChecked="{x:Bind ViewModel.IsOnAccount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

<RadioButton
    Content="Cash"
    GroupName="account"
    IsChecked="{Binding ElementName=rdo_on_account, Path=IsChecked, Converter={StaticResource BoolInvert}}" />
    
</StackPanel>



public class BoolInvert : IValueConverter
{
// convert the value to the destination format
public object Convert(object value, Type targetType, object parameter, string language)
{
    if (value is bool)
    {
        if ((bool)value == true)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    //not a bool
    return value;
}

// convert from the destination format to the source format
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
    return value;
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文