【发布时间】:2011-03-22 15:22:34
【问题描述】:
我有一个带有复选框的布尔类型属性。
我想将其更改为绑定在相同属性上的两个单选按钮,呈现值 true/false。
如何做到这一点?
【问题讨论】:
标签: wpf binding radio-button boolean
我有一个带有复选框的布尔类型属性。
我想将其更改为绑定在相同属性上的两个单选按钮,呈现值 true/false。
如何做到这一点?
【问题讨论】:
标签: wpf binding radio-button boolean
您可以使用一个值转换器来恢复布尔值:
使用该转换器,将一个 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}}" />
请注意,转换器只是一个简单的例子。如果您想在生产代码中使用它,请巧妙地实现它。我还没有测试过。如果它不起作用,请发表评论。
【讨论】:
<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 属性设置为相同的值,则无需转换器即可实现此目的(因此当时只能检查一个)。然后,将一个单选按钮的 IsChecked 设置为“True”,并将另一个单选按钮的 IsChecked 绑定到您的布尔值。切换单选按钮会更改布尔值,但是,将布尔值更改为 False 不会检查其他单选按钮。
谢谢, 弗拉德
【讨论】:
下面是如何通过示例代码将单选按钮绑定到任何类型(枚举、布尔值、字符串、整数等)的解决方案:
http://www.codeproject.com/Tips/720497/Binding-Radio-Buttons-to-a-Single-Property
【讨论】:
标准绑定方法有一个不幸的副作用,即在加载 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,因为我总是将它用作单选按钮的转换器。
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;
【讨论】:
如果您希望 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;
}
}
其余的和他的回答一样。
【讨论】:
当使用 MVVMLight 和 DataContext 在 XAML 中设置为:
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}"/>
【讨论】:
CommandParameter 的自定义转换器来避免 SOE。例如。 Yes 选项与CommandParameter=1,No 选项与CommandParameter=2