I talked about working with CheckBoxes in my previous article and mentioned briefly how you can have them behave like a Radio button, but in the end, nothing beats the actual thing no matter how close you can make another control behave. A Radio button only allows a single selection for its specific group. When you select something else, the current item will be unchecked while the new item is checked and there are only two options unlike a checkbox: Checked and Unchecked.
#Build the GUI [xml]$xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen" SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray"> <StackPanel > <RadioButton x:Name="Item1" Content = 'Item1'/> <RadioButton x:Name="Item2" Content = 'Item2'/> <RadioButton x:Name="Item3" Content = 'Item3'/> <TextBox /> </StackPanel> </Window> "@ $reader=(New-Object System.Xml.XmlNodeReader $xaml) $Window=[Windows.Markup.XamlReader]::Load( $reader ) $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) } $Window.Showdialog() | Out-Null
Nothing really special here. I use <RadioButton> in my XAML code to create the control. By default, every radio button is part of a default group which means that all radio buttons will follow the same suit of being unchecked while a single button is checked. There is a property that you can use called GroupName which can be used to (as the name implies) group radio buttons to handle different parts and lets you have multiple selections with radio buttons.
#Build the GUI [xml]$xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen" SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray"> <StackPanel > <RadioButton x:Name="Item1" Content = 'Item1(Group1)' GroupName='Group1'/> <RadioButton x:Name="Item2" Content = 'Item2(Group1)' GroupName='Group1'/> <RadioButton x:Name="Item3" Content = 'Item3(Group1)' GroupName='Group1'/> <Separator/> <RadioButton x:Name="Item4" Content = 'Item4(Group2)' GroupName='Group2'/> <RadioButton x:Name="Item5" Content = 'Item5(Group2)' GroupName='Group2'/> <RadioButton x:Name="Item6" Content = 'Item6(Group2)' GroupName='Group2'/> <TextBox /> </StackPanel> </Window> "@ $reader=(New-Object System.Xml.XmlNodeReader $xaml) $Window=[Windows.Markup.XamlReader]::Load( $reader ) $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) } $Window.Showdialog() | Out-Null
Anything in Group1 is bound by the limitations of the radio button and the same goes for the items in Group2. Only one item in each group can be checked, but because I am using GroupNames, I can have one of each checked in their respective groups.
If you are not a fan of the default foreground and background colors, we can change those up as well using the Background and Foreground properties in the XAML code.
#Build the GUI [xml]$xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen" SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray"> <StackPanel x:Name='StackPanel'> <RadioButton x:Name="Item1" Content = 'Item1(Group1)' GroupName='Group1' Background='Black' Foreground='Red'/> <RadioButton x:Name="Item2" Content = 'Item2(Group1)' GroupName='Group1' Background='Black' Foreground='Red'/> <RadioButton x:Name="Item3" Content = 'Item3(Group1)' GroupName='Group1' Background='Black' Foreground='Red'/> <Separator/> <RadioButton x:Name="Item4" Content = 'Item4(Group2)' GroupName='Group2' Background='Yellow' Foreground='Blue'/> <RadioButton x:Name="Item5" Content = 'Item5(Group2)' GroupName='Group2' Background='Yellow' Foreground='Blue'/> <RadioButton x:Name="Item6" Content = 'Item6(Group2)' GroupName='Group2' Background='Yellow' Foreground='Blue'/> <TextBox /> </StackPanel> </Window> "@ $reader=(New-Object System.Xml.XmlNodeReader $xaml) $Window=[Windows.Markup.XamlReader]::Load( $reader ) $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) } $Window.Showdialog() | Out-Null
The background property defines the background color of the radio button itself while the foreground property defines the text and the radio button when it has been checked.
Much like a Checkbox, we can find out which button is checked using the IsChecked property.
$StackPanel.Children | Where { $_ -is [system.windows.controls.radiobutton] -and $_.IsChecked } | Select Name
We can also handle events much like the checkboxes on the Checked event.
#Build the GUI [xml]$xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen" SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray"> <StackPanel x:Name='StackPanel'> <RadioButton x:Name="Item1" Content = 'Item1'/> <RadioButton x:Name="Item2" Content = 'Item2'/> <RadioButton x:Name="Item3" Content = 'Item3'/> <Separator/> <TextBox x:Name='textbox'/> </StackPanel> </Window> "@ $reader=(New-Object System.Xml.XmlNodeReader $xaml) $Window=[Windows.Markup.XamlReader]::Load( $reader ) $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) -Scope Script } #Bubble up event handler [System.Windows.RoutedEventHandler]$Script:CheckedEventHandler = { $TextBox.Text = $_.source.name } $StackPanel.AddHandler([System.Windows.Controls.RadioButton]::CheckedEvent, $CheckedEventHandler) $Window.Showdialog() | Out-Null
The magic here happens with the following code:
#Bubble up event handler [System.Windows.RoutedEventHandler]$Script:CheckedEventHandler = { $TextBox.Text = $_.source.name } $StackPanel.AddHandler([System.Windows.Controls.RadioButton]::CheckedEvent, $CheckedEventHandler)
I a creating a routed event handler which is basically a script block that be used when a specified event occurs. In this case, the scriptblock just takes the object returned from the event (System.Windows.RoutedEventArgs).
The scriptblock then uses the Source property which has the control object (radio button) that we can then use to update the textbox. I set the event handler on the StackPanel which allows me to not have to worry about setting the event handler on each radio button.
That is all to working with Radio buttons in WPF using PowerShell. If you have any questions or other things that you would like to see, feel free to leave a comment!
This article looks like what I’ve after. I’ve got two radio button and one check box. I want the checkbox to only be enabled if the bottom radio is checked. I can get it to come alive when the bottom radio is checked but can’t get Is.Enabled to be False when the top one is checked.
Desired outcome:
RadioButton 1 is checked by default and the checkbox is not enabled. Checkbox becomes enabled only if RadioButton 2 is checked. The returned to default state if RadioButton 1 is checked, making the Checkbox 1 hidden again.
RadioButton 1
RadioButton 2
Checkbox 1
I could only get it half working by using the long handler method.
$WPFradioButton1.AddHandler([Windows.Controls.RadioButton]::CheckedEvent, [Windows.RoutedEventHandler]{$WPFcheckBox.IsEnabled = ‘True’})
$WPFradioButton1.AddHandler([Windows.Controls.RadioButton]::UncheckedEvent, [Windows.RoutedEventHandler]{$WPFcheckBox.IsEnabled = ‘False’})
Am I using my opposite condition wrong?
This is awesome. Thanks!