简单的WPF RadioButton绑定?

将一组3个单选button绑定到值为1,2或3的inttypes属性的最简单方法是什么?

实际上,使用像这样的转换器打破了双向绑定,正如我上面所说的,你也不能在枚举中使用它。 更好的方法是使用ListBox的简单样式,如下所示:

注意:与DrWPF.com在他们的例子中所说的相反,不要把ContentPresenter放在RadioButton中,否则如果你添加一个包含诸如button之类的内容的项目,你将不能设置焦点或者与其交互。 这个技术解决了这个问题。 此外,您需要处理文本的灰色以及删除标签上的边距,否则将无法正确呈现。 这种风格也适合你。

<Style x:Key="RadioButtonListItem" TargetType="{x:Type ListBoxItem}" > <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem"> <DockPanel LastChildFill="True" Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Center" > <RadioButton IsChecked="{TemplateBinding IsSelected}" Focusable="False" IsHitTestVisible="False" VerticalAlignment="Center" Margin="0,0,4,0" /> <ContentPresenter Content = "{TemplateBinding ContentControl.Content}" ContentTemplate = "{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat = "{TemplateBinding ContentControl.ContentStringFormat}" HorizontalAlignment = "{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment = "{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels = "{TemplateBinding UIElement.SnapsToDevicePixels}" /> </DockPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="RadioButtonList" TargetType="ListBox"> <Style.Resources> <Style TargetType="Label"> <Setter Property="Padding" Value="0" /> </Style> </Style.Resources> <Setter Property="BorderThickness" Value="0" /> <Setter Property="Background" Value="Transparent" /> <Setter Property="ItemContainerStyle" Value="{StaticResource RadioButtonListItem}" /> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBox}"> <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" /> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="TextBlock.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" /> </Trigger> </Style.Triggers> </Style> <Style x:Key="HorizontalRadioButtonList" BasedOn="{StaticResource RadioButtonList}" TargetType="ListBox"> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <VirtualizingStackPanel Background="Transparent" Orientation="Horizontal" /> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style> 

你现在有单选button的外观和感觉,但你可以做双向绑定,你可以使用枚举。 就是这样…

 <ListBox Style="{StaticResource RadioButtonList}" SelectedValue="{Binding SomeVal}" SelectedValuePath="Tag"> <ListBoxItem Tag="{x:Static l:MyEnum.SomeOption}" >Some option</ListBoxItem> <ListBoxItem Tag="{x:Static l:MyEnum.SomeOtherOption}">Some other option</ListBoxItem> <ListBoxItem Tag="{x:Static l:MyEnum.YetAnother}" >Yet another option</ListBoxItem> </ListBox> 

此外,由于我们明确地分离出了将ListBoxItem进行转换的样式,而不是像其他示例所示的那样将其replace为内联,现在可以创build一个新的样式来根据每个项目(如间距)自定义事件。 (如果您只是尝试将ListBoxItem作为键控样式覆盖generics控件目标,则这将不起作用。)

以下是每个项目上下各有6个保证金的示例。 (请注意,您必须通过ItemContainerStyle属性显式应用样式,而不是简单地按照上述原因在ListBox的资源部分中定位ListBoxItem。)

 <Window.Resources> <Style x:Key="SpacedRadioButtonListItem" TargetType="ListBoxItem" BasedOn="{StaticResource RadioButtonListItem}"> <Setter Property="Margin" Value="0,6" /> </Style> </Window.Resources> <ListBox Style="{StaticResource RadioButtonList}" ItemContainerStyle="{StaticResource SpacedRadioButtonListItem}" SelectedValue="{Binding SomeVal}" SelectedValuePath="Tag"> <ListBoxItem Tag="{x:Static l:MyEnum.SomeOption}" >Some option</ListBoxItem> <ListBoxItem Tag="{x:Static l:MyEnum.SomeOtherOption}">Some other option</ListBoxItem> <ListBoxItem Tag="{x:Static l:MyEnum.YetAnother}" >Ter another option</ListBoxItem> </ListBox> 

希望这有助于,当然,如果你喜欢这个,请标记为接受或投票给我! 🙂

我想出了一个简单的解决scheme。

我有一个model.cs类与:

 private int _isSuccess; public int IsSuccess { get { return _isSuccess; } set { _isSuccess = value; } } 

我有DataContext设置为model.cs Window1.xaml.cs文件。 xaml包含单选button:

 <RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=1}" Content="one" /> <RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=2}" Content="two" /> <RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=3}" Content="three" /> 

这是我的转换器:

 public class RadioBoolToIntConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { int integer = (int)value; if (integer==int.Parse(parameter.ToString())) return true; else return false; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return parameter; } } 

当然,在Window1的资源中:

 <Window.Resources> <local:RadioBoolToIntConverter x:Key="radioBoolToIntConverter" /> </Window.Resources> 

我知道这是过时的方式,但我有一个更轻,更简单的替代解决scheme。 从System.Windows.Controls.RadioButton派生一个类,并声明两个依赖属性RadioValueRadioBinding 。 然后在类代码中,重写OnChecked并将RadioBinding属性值设置为RadioBinding属性值的值。 另一方面,使用callback陷阱更改为RadioBinding属性,并且如果新值等于RadioValue属性的值,请将其IsChecked属性设置为true

代码如下:

 public class MyRadioButton : RadioButton { public object RadioValue { get { return (object)GetValue(RadioValueProperty); } set { SetValue(RadioValueProperty, value); } } // Using a DependencyProperty as the backing store for RadioValue. This enables animation, styling, binding, etc... public static readonly DependencyProperty RadioValueProperty = DependencyProperty.Register( "RadioValue", typeof(object), typeof(MyRadioButton), new UIPropertyMetadata(null)); public object RadioBinding { get { return (object)GetValue(RadioBindingProperty); } set { SetValue(RadioBindingProperty, value); } } // Using a DependencyProperty as the backing store for RadioBinding. This enables animation, styling, binding, etc... public static readonly DependencyProperty RadioBindingProperty = DependencyProperty.Register( "RadioBinding", typeof(object), typeof(MyRadioButton), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnRadioBindingChanged)); private static void OnRadioBindingChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { MyRadioButton rb = (MyRadioButton)d; if (rb.RadioValue.Equals(e.NewValue)) rb.SetCurrentValue(RadioButton.IsCheckedProperty, true); } protected override void OnChecked(RoutedEventArgs e) { base.OnChecked(e); SetCurrentValue(RadioBindingProperty, RadioValue); } } 

XAML用法:

 <my:MyRadioButton GroupName="grp1" Content="Value 1" RadioValue="val1" RadioBinding="{Binding SelectedValue}"/> <my:MyRadioButton GroupName="grp1" Content="Value 2" RadioValue="val2" RadioBinding="{Binding SelectedValue}"/> <my:MyRadioButton GroupName="grp1" Content="Value 3" RadioValue="val3" RadioBinding="{Binding SelectedValue}"/> <my:MyRadioButton GroupName="grp1" Content="Value 4" RadioValue="val4" RadioBinding="{Binding SelectedValue}"/> 

希望有人觉得这有用之后:)

我很惊讶没有人提出这种解决scheme来绑定它与布尔arrays。 它可能不是最干净的,但它可以很容易地使用:

 private bool[] _modeArray = new bool[] { true, false, false}; public bool[] ModeArray { get { return _modeArray ; } } public int SelectedMode { get { return Array.IndexOf(_modeArray, true); } } 

在XAML中:

 <RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[0], Mode=TwoWay}"/> <RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[1], Mode=TwoWay}"/> <RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[2], Mode=TwoWay}"/> 

注意:如果你不想在默认情况下选中,你不需要双向绑定。 双向绑定是这个解决scheme的最大缺点。

优点:

  • 不需要代码
  • 无需额外的类(IValue转换器)
  • 不需要额外的枚举
  • 不需要bizzare绑定
  • 简单易懂
  • 不违反MVVM(呃,至less我希望如此)

有时可以像这样在模型中解决它:假设你有3个布尔型属性OptionA,OptionB,OptionC。

XAML:

 <RadioButton IsChecked="{Binding OptionA}"/> <RadioButton IsChecked="{Binding OptionB}"/> <RadioButton IsChecked="{Binding OptionC}"/> 

码:

 private bool _optionA; public bool OptionA { get { return _optionA; } set { _optionA = value; if( _optionA ) { this.OptionB= false; this.OptionC = false; } } } private bool _optionB; public bool OptionB { get { return _optionB; } set { _optionB = value; if( _optionB ) { this.OptionA= false; this.OptionC = false; } } } private bool _optionC; public bool OptionC { get { return _optionC; } set { _optionC = value; if( _optionC ) { this.OptionA= false; this.OptionB = false; } } } 

你明白了。 不是最干净的事情,但容易。

这个例子可能看起来有点冗长,但是它的意图应该很清楚。

它在ViewModel中使用3个布尔属性,称为FlagForValue1FlagForValue2FlagForValue3 。 这三个属性中的每一个都由名为_intValue的单个私有字段_intValue

视图(xaml)的3个单选button每个绑定到视图模型中相应的Flag属性。 这意味着显示“值1”的单选button绑定到视图模型中的FlagForValue1布尔属性,其他两个相应地绑定。

当在视图模型中设置其中一个属性(例如FlagForValue1 )时,对于其他两个属性(例如FlagForValue2FlagForValue3 )也会引发属性更改事件,所以UI(WPF INotifyPropertyChanged基础结构)可以select/取消select每个单选button正确。

  private int _intValue; public bool FlagForValue1 { get { return (_intValue == 1) ? true : false; } set { _intValue = 1; RaisePropertyChanged("FlagForValue1"); RaisePropertyChanged("FlagForValue2"); RaisePropertyChanged("FlagForValue3"); } } public bool FlagForValue2 { get { return (_intValue == 2) ? true : false; } set { _intValue = 2; RaisePropertyChanged("FlagForValue1"); RaisePropertyChanged("FlagForValue2"); RaisePropertyChanged("FlagForValue3"); } } public bool FlagForValue3 { get { return (_intValue == 3) ? true : false; } set { _intValue = 3; RaisePropertyChanged("FlagForValue1"); RaisePropertyChanged("FlagForValue2"); RaisePropertyChanged("FlagForValue3"); } } 

xaml看起来像这样:

  <RadioButton GroupName="Search" IsChecked="{Binding Path=FlagForValue1, Mode=TwoWay}" >Value 1</RadioButton> <RadioButton GroupName="Search" IsChecked="{Binding Path=FlagForValue2, Mode=TwoWay}" >Value 2</RadioButton> <RadioButton GroupName="Search" IsChecked="{Binding Path=FlagForValue3, Mode=TwoWay}" >Value 3</RadioButton>