PowerShell and WPF: Radio Button

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

 

image

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

image

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

image

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

 

image

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

 

image

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).

image

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 entry was posted in powershell, WPF and tagged , , , . Bookmark the permalink.

2 Responses to PowerShell and WPF: Radio Button

  1. EM says:

    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?

  2. webmastir says:

    This is awesome. Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s