如何取消选中 WPF (MVVM) 中的单选按钮
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32719839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Uncheck radio button in WPF (MVVM)
提问by overcomer
I have a radio buttons group. The choice is not mandatory to fill the form. At the beginning all the radio buttons are unchecked. If the user unintentionally clicks on one of them, he can not go back, because at least one has to be checked.
我有一个单选按钮组。选择不是填写表格的强制性要求。开始时,所有单选按钮都未选中。如果用户无意中点击了其中之一,他将无法返回,因为至少要检查一个。
So How can I uncheck a radio button and not force the user to make an unwanted choice?
那么如何取消选中单选按钮而不强迫用户做出不需要的选择呢?
p.s. the form is built at run-time and I am following the MVVM design pattern. For Mandatory choices, the radio buttons solution fit very well and I already use it in this case.
ps 表单是在运行时构建的,我遵循 MVVM 设计模式。对于强制选择,单选按钮解决方案非常适合,我已经在这种情况下使用它。
采纳答案by Rachel
Personally when I want this behavior I use a ListBoxwith the Template overwritten to use RadioButtons.
就我个人而言,当我想要这种行为时,我使用 aListBox与模板覆盖以使用RadioButtons.
It's the best control suited to do all of the following :
这是适合执行以下所有操作的最佳控件:
- display a list of items
- only one item can be selected at a time, so only one property maintained in data model
- user can leave selected item as null, indicating no item is selected
- 显示项目列表
- 一次只能选择一项,因此数据模型中只维护一个属性
- 用户可以将所选项目保留为空,表示未选择任何项目
My custom style for the ListBoxremoves the borders and background color, and draws each item using a RadioButtonwith the IsCheckedbound to the ListBoxItem.IsSelected. Typically something like this :
我的自定义样式ListBox删除边框和背景颜色,并使用绘制每个项目RadioButton与IsChecked绑定ListBoxItem.IsSelected。通常是这样的:
<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2, 2, 2, 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="Transparent">
<RadioButton
Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
And to display the RadioButtons themselves is usually something very simple, like this :
并且显示 RadioButtons 本身通常非常简单,如下所示:
<ListBox ItemsSource="{Binding AvailableValues}"
SelectedValue="{Binding SelectedValue}"
Style="{StaticResource RadioButtonListBoxStyle}" />
回答by Peter Moore
Try this:
尝试这个:
public class OptionalRadioButton : RadioButton
{
#region bool IsOptional dependency property
public static DependencyProperty IsOptionalProperty =
DependencyProperty.Register(
"IsOptional",
typeof(bool),
typeof(OptionalRadioButton),
new PropertyMetadata((bool)true,
(obj, args) =>
{
((OptionalRadioButton)obj).OnIsOptionalChanged(args);
}));
public bool IsOptional
{
get
{
return (bool)GetValue(IsOptionalProperty);
}
set
{
SetValue(IsOptionalProperty, value);
}
}
private void OnIsOptionalChanged(DependencyPropertyChangedEventArgs args)
{
// TODO: Add event handler if needed
}
#endregion
protected override void OnClick()
{
bool? wasChecked = this.IsChecked;
base.OnClick();
if ( this.IsOptional && wasChecked == true )
this.IsChecked = false;
}
}
回答by dba
I used for this Scenario some Eventhandlers
我在这个场景中使用了一些事件处理程序
<RadioButton Checked="RB_Checked" Click="RB_Clicked"/>
In the Codebehind of the XAML:
在 XAML 的代码隐藏中:
Private JustChecked as Boolean
Private Sub RB_Checked(sender As Object, e As RoutedEventArgs)
Dim s As RadioButton = sender
' Action on Check...
JustChecked = True
End Sub
Private Sub RB_Clicked(sender As Object, e As RoutedEventArgs)
If JustChecked Then
JustChecked = False
e.Handled = True
Return
End If
Dim s As RadioButton = sender
If s.IsChecked Then s.IsChecked = False
End Sub
Or in C#
或者在 C# 中
private bool JustChecked;
private void RB_Checked(object sender, RoutedEventArgs e)
{
RadioButton s = sender;
// Action on Check...
JustChecked = true;
}
private void RB_Clicked(object sender, RoutedEventArgs e)
{
if (JustChecked) {
JustChecked = false;
e.Handled = true;
return;
}
RadioButton s = sender;
if (s.IsChecked)
s.IsChecked = false;
}
Click Event fires after Checked Event
单击事件在检查事件后触发
回答by Bohdan Biehov
The dirty way is to create collapsed RadioButton
肮脏的方法是创建折叠的 RadioButton
<StackPanel>
<RadioButton Content="Option 1" GroupName="optionSet1" PreviewMouseDown="RadioButton_OnPreviewMouseDown"/>
<RadioButton Content="Option 2" GroupName="optionSet1" PreviewMouseDown="RadioButton_OnPreviewMouseDown"/>
<RadioButton GroupName="optionSet1" x:Name="rbEmpty" Visibility="Collapsed" />
</StackPanel>
And check the empty RadioButton if user click on already checked RadioButton
如果用户单击已选中的 RadioButton,则检查空的 RadioButton
Code behind
背后的代码
private void RadioButton_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var radioButton = sender as RadioButton;
if (radioButton.IsChecked.GetValueOrDefault())
{
rbEmpty.IsChecked = true;
e.Handled = true;
}
}
回答by Tono Nam
Your radio button:
您的单选按钮:
<RadioButton x:Name="MyRadioButton">Some Radio Button</RadioButton>
Code Behind:
背后的代码:
MyRadioButton.IsChecked = false;
If you want to uncheck it using bindings then do:
如果要使用绑定取消选中它,请执行以下操作:
Code behind:
后面的代码:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion
private bool _isRadioChecked;
public bool IsRadioChecked
{
get
{
return _isRadioChecked;
}
set
{
_isRadioChecked = value;
OnPropertyChanged("IsRadioChecked");
}
}
}
xaml (view):
xaml(查看):
<RadioButton IsChecked="{Binding IsRadioChecked}">Some Radio Button</RadioButton>
回答by Fabio Salvalai
You could, as @Tomtom pointed out, use Checkboxes, but that would also give the opportunity to check more than one option at the same time, oryou'd have to implement a complex mechanism to make sure only one option is checked at a time.
正如@Tomtom 指出的那样,您可以使用复选框,但这也将提供同时检查多个选项的机会,或者您必须实施一种复杂的机制来确保一次只检查一个选项时间。
Another very cheap workaround would be to add an extra entry in your radio button choices.
另一个非常便宜的解决方法是在您的单选按钮选项中添加一个额外的条目。
How did you hear about us ?
您是怎么知道我们的 ?
- A friend
- an ad on TV
- Other
- 谷歌
- 一个朋友
- 电视广告
- 其他
回答by Bobby
I agree with Tomtom that RadioButtonis perhaps not the best design choice, but if that selection is out of your control or it is necessary for other reasons, you will need some mechanism by which to force the deselect.
我同意 Tomtom 的观点,这RadioButton可能不是最佳设计选择,但如果该选择超出您的控制范围或由于其他原因而有必要,您将需要某种机制来强制取消选择。
Here are some possibilities:
这里有一些可能性:
- A Clear button near the
RadioButtongroup - Deselect a
RadioButtonthat is already checked if it is clicked again. - Provide a context menu Clear option when a checked
RadioButtonis right clicked
RadioButton组附近的清除按钮RadioButton如果再次单击,则取消选择已选中的一个。RadioButton右键单击选中的对象时提供上下文菜单清除选项
Since the form is built at run-time, you will need to attach the appropriate event handler when you are creating the control, like so:
由于表单是在运行时构建的,因此您需要在创建控件时附加适当的事件处理程序,如下所示:
// Create an instance of the control
var controlType = typeof(Control).Assembly.GetType(fullyQualifiedControl, true);
var control = Activator.CreateInstance(controlType);
switch (fullyQualifiedControl)
{
case "System.Windows.Controls.RadioButton":
((RadioButton)control).Checked += new RoutedEventHandler(DataDrivenControl_Checked);
((RadioButton)control).Unchecked += new RoutedEventHandler(DataDrivenControl_UnChecked);
break;
}
回答by RobDev
I know that this is a bit late in the day for an answer but I had a similar problem using UWP and I thought that this might help. I was developing a custom menu where the user can pick and unpick an option and my solution is shown in the following test code:
我知道今天的答案有点晚了,但我在使用 UWP 时遇到了类似的问题,我认为这可能会有所帮助。我正在开发一个自定义菜单,用户可以在其中选择和取消选择一个选项,我的解决方案显示在以下测试代码中:
Main Page Xaml:
主页 Xaml:
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<RadioButton x:Name="RB1" GroupName="RBTest" Content="Item No. 1" Click="RBtn_Click"/>
<RadioButton x:Name="RB2" GroupName="RBTest" Content="Item No. 2" Click="RBtn_Click"/>
<RadioButton x:Name="RB3" GroupName="RBTest" Content="Item No. 3" Click="RBtn_Click"/>
<RadioButton x:Name="RB4" GroupName="RBTest" Content="Item No. 4" Click="RBtn_Click"/>
<RadioButton x:Name="RB5" GroupName="RBTest" Content="Item No. 5" Click="RBtn_Click"/>
</StackPanel>
</Grid>
Main Page Code Behind:
后面的主页代码:
public sealed partial class MainPage : Page
{
private bool rb1PrevState;
private bool rb2PrevState;
private bool rb3PrevState;
private bool rb4PrevState;
private bool rb5PrevState;
public MainPage()
{
this.InitializeComponent();
rb1PrevState = this.RB1.IsChecked.Value;
rb2PrevState = this.RB2.IsChecked.Value;
rb3PrevState = this.RB3.IsChecked.Value;
rb4PrevState = this.RB4.IsChecked.Value;
rb5PrevState = this.RB5.IsChecked.Value;
}
private void RBtn_Click(object sender, RoutedEventArgs e)
{
RadioButton rbtn = sender as RadioButton;
if (rbtn != null)
{
if (rbtn.IsChecked.Value == true)
{
switch (rbtn.Name)
{
case "RB1":
if (rb1PrevState == true)
{
rbtn.IsChecked = false;
rb1PrevState = false;
}
else
{
rb1PrevState = true;
ResetRBPrevStates("RB1");
}
break;
case "RB2":
if (rb2PrevState == true)
{
rbtn.IsChecked = false;
rb2PrevState = false;
}
else
{
rb2PrevState = true;
ResetRBPrevStates("RB2");
}
break;
case "RB3":
if (rb3PrevState == true)
{
rbtn.IsChecked = false;
rb3PrevState = false;
}
else
{
rb3PrevState = true;
ResetRBPrevStates("RB3");
}
break;
case "RB4":
if (rb4PrevState == true)
{
rbtn.IsChecked = false;
rb4PrevState = false;
}
else
{
rb4PrevState = true;
ResetRBPrevStates("RB4");
}
break;
case "RB5":
if (rb5PrevState == true)
{
rbtn.IsChecked = false;
rb5PrevState = false;
}
else
{
rb5PrevState = true;
ResetRBPrevStates("RB5");
}
break;
default:
break;
}
}
}
}
private void ResetRBPrevStates(string _excludeRB)
{
rb1PrevState = (_excludeRB == "RB1" ? rb1PrevState : false);
rb2PrevState = (_excludeRB == "RB2" ? rb2PrevState : false);
rb3PrevState = (_excludeRB == "RB3" ? rb3PrevState : false);
rb4PrevState = (_excludeRB == "RB4" ? rb4PrevState : false);
rb5PrevState = (_excludeRB == "RB5" ? rb5PrevState : false);
}
}
This worked well for me and, a far as I'm concerned, doesn't break any MVVM rules.
这对我来说效果很好,而且就我而言,不会违反任何 MVVM 规则。
回答by luka
hi this is how to check and uncheck the radio button each times click on it.
嗨,这是每次单击单选按钮时检查和取消选中它的方法。
int click = 0;
private void RadioButton_Click(object sender, RoutedEventArgs e)
{
click++;
((RadioButton)sender).IsChecked = click % 2 == 1 ;
click %= 2;
}
回答by Bruno V
A RadioButtoncannot be unchecked.
If you have to keep using RadioButtons, I would add a default 'Not selected' choice.
In this case, I prefer a ComboBoxwith an empty item or clear button at the top.
ARadioButton不能取消选中。如果您必须继续使用RadioButtons,我会添加一个默认的“未选择”选项。在这种情况下,我更喜欢ComboBox顶部有一个空项目或清除按钮。

