Introduction
There are times when there could be a number of RadioButton
controls, and after the containing Control
loses Visibility
, it is desirable that none of the RadioButton
controls be selected. This can be done usually in the associated ViewModel
, but it could be easier just to have the controls reset automatically, sort of like when you initially create a View
, then any contained RadioButton
is false
unless the ViewModel
has set it to true
, and the ViewModel
will also have the default of false
for any property, including those associated with a RadioButton
IsChecked
property.
The Behavior
The following is the C# code for the behavior:
public class ResetRadioButtonOnVisibilityBehavior
{
public static bool GetEnable(DependencyObject obj)
{
return (bool)obj.GetValue(EnableProperty);
}
public static void SetEnable(DependencyObject obj, bool value)
{
obj.SetValue(EnableProperty, value);
}
public static readonly DependencyProperty EnableProperty =
DependencyProperty.RegisterAttached("Enable",
typeof(bool), typeof(ResetRadioButtonOnVisibilityBehavior),
new UIPropertyMetadata(OnEnablePropertyChanged));
private static void OnEnablePropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var element = (FrameworkElement) d;
if ((bool)e.NewValue)
element.IsVisibleChanged += ElementOnIsVisibleChanged;
else
element.IsVisibleChanged -= ElementOnIsVisibleChanged;
}
private static void ElementOnIsVisibleChanged(object sender,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var dependencyObject = (UIElement)sender;
if (!(bool) dependencyPropertyChangedEventArgs.NewValue)
{
var checkBoxes = FindVisualChildren<ToggleButton>(dependencyObject).ToList();
checkBoxes.ForEach(i => i.IsChecked = false);
}
}
#region private static
private static IEnumerable<T> FindVisualChildren<T>(DependencyObject root)
where T : DependencyObject
{
if (root != null)
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(root, i);
if (child is T) yield return (T)child;
foreach (T childOfChild in FindVisualChildren<T>(child))
yield return childOfChild;
}
}
#endregion
}
There is a single bool
EnableProperty
DependencyProperty
that is set to true
to enable the behavior. The event
handler for its DependencyProperty
changed event, OnEnablePropertyChanged
, adds the method ElementOnIsVisibleChanged
to the IsVisibleChanged
event (or removes it if set to false
). When the e.NewValue
part of the DependencyPropertyChangedEventArgs
argument is false
, then the Control
's VisualChildren
are searched for any instances of a RadioButton
, and any RadioButton
controls that are found have their IsChecked
property set to false
.
I have included the private
method FindVisualChildren
in the behavior for probability, but more than likely would want to put this code in a separate class within the solution for utility code.
The Sample
To use the sample, you just have to click the ToggleButton
on the Window
so that RadioButton
controls within a StackPanel
to which this behavior is attached are visible, then can select any number of the RadioButton
controls which results in exactly one of them being set. Hide and show the RadioButton
controls using the ToggleButton
. Notice that none of the RadioButton
controls is set when the StackPanel
Visibility
is Visible
.
Using the Code
Using this behavior is like any other behavior, the behavior is included in the XAML for the parent or grandparent, or any other ancestor Control
containing RadioButton
controls. Its Enable
property just has to be set to true
:
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
local:ResetRadioButtonOnVisibilityBehavior.Enable="True"
Visibility="{Binding ElementName=ToggleButton,
Path=IsChecked,
Converter={local:IsTrueConverter},
ConverterParameter=Visible:Hidden}">
<RadioButton Content="RadioButton One" />
<RadioButton Content="RadioButton One" />
<RadioButton Content="RadioButton One" />
<RadioButton Content="RadioButton One" />
</StackPanel>
Design Issues
This is quite a stupid design since all instances of RadioButton
controls within the Control
that this behavior is attached will be reset. This could be considered a good or bad thing because the way a group of RadioButton
controls act is that checking a RadioButton
will only reset those RadioButton
controls directly within the same container. However, if it is desired to reset one group of contained RadioButton
controls, then likely that want to reset all.
This behavior affects RadioButton
controls but could also be very easily modified to work on CheckBox
or ToggleButton
controls.
History
- 04/02/2018: Initial version