Search code examples
wpfpowershellfunction

Powershell event Add_Checked, Add_Unchecked does not occur in custom function


Since I need to create this pattern multiple times in a WPF window, I created a function like below.

function Group_WPF {
    param (
        [Windows.Controls.Canvas]$canvas,
        [int]$top,
        [ref]$f1,
        [string]$n1,
        [ref]$f2,
        [string]$n2,
        [ref]$isR,
        [ref]$isB,
        [ref]$bu,
    )

    $f1.Value = New-Object Windows.Controls.TextBox
    $f1.Value.Width = 380
    [Windows.Controls.Canvas]::SetLeft($f1.Value, 10)
    [Windows.Controls.Canvas]::SetTop($f1.Value, $top + 25)
    $canvas.Children.Add($f1.Value)

    $f1.Value.Add_MouseDoubleClick({
        param ($source, $e)
        $source.SelectAll()
    })

    $f2.Value = New-Object Windows.Controls.TextBox
    $f2.Value.Width = 380
    [Windows.Controls.Canvas]::SetRight($f2.Value, 10)
    [Windows.Controls.Canvas]::SetTop($f2.Value, $top + 25)
    $canvas.Children.Add($f2.Value)

    $f2.Value.Add_MouseDoubleClick({
        param ($source, $e)
        $source.SelectAll()
    })

    $isR.Value = New-Object Windows.Controls.CheckBox
    $isR.Value.Content = "Re"
    $isR.Value.IsChecked = $true
    [Windows.Controls.Canvas]::SetLeft($isR.Value, 210)
    [Windows.Controls.Canvas]::SetTop($isR.Value, $top + 50)
    $canvas.Children.Add($isR.Value)

    $isB.Value = New-Object Windows.Controls.CheckBox
    $isB.Value.Content = "Bu"
    [Windows.Controls.Canvas]::SetLeft($isB.Value, 290)
    [Windows.Controls.Canvas]::SetTop($isB.Value, $top + 50)
    $canvas.Children.Add($isB.Value)

    $bu.Value = New-Object Windows.Controls.TextBox
    $bu.Value.Width = 380
    $bu.Value.IsReadOnly = $true
    $bu.Value.Background = [System.Windows.Media.Brushes]::Gainsboro
    [Windows.Controls.Canvas]::SetRight($bu.Value, 10)
    [Windows.Controls.Canvas]::SetTop($bu.Value, $top + 50)
    $canvas.Children.Add($bu.Value)

    $bu.Value.Add_MouseDoubleClick({
        param ($source, $e)
        $source.SelectAll()
    })

    $isB.Value.Add_Checked({
        $bu.Value.IsReadOnly = $false
        $bu.Value.Background = [System.Windows.Media.Brushes]::White
        $isR.Value.IsChecked = $false
    })

    $isB.Value.Add_Unchecked({
        $bu.Value.IsReadOnly = $true
        $bu.Value.Background = [System.Windows.Media.Brushes]::Gainsboro
    })

    $isR.Value.Add_Checked({
        $isB.Value.IsChecked = $false
    })
}

All works, except the Add_Checked and Add_Unchecked events. When I tried them, I received the following error:

The property 'IsReadOnly' cannot be found on this object. Verify that the property exists and can be set.
At line:111 char:9
+         $bu.Value.IsReadOnly = $false

The property 'Background' cannot be found on this object. Verify that the property exists and can be set.
At line:112 char:9
+         $bu.Value.Background = [System.Windows.Media.Brushes]::White

The property 'IsChecked' cannot be found on this object. Verify that the property exists and can be set.
At line:113 char:9
+         $isR.Value.IsChecked = $false

Please forgive me for my stupidity. Please guide me how to solve this problem. Sincerely thank you.


Solution

  • Because you need the local variables from the caller context (ie: $bu, $isR and $isB) you need to call GetNewClosure:

    $isB.Value.Add_Checked({
        $bu.Value.IsReadOnly = $false
        $bu.Value.Background = [System.Windows.Media.Brushes]::White
        $isR.Value.IsChecked = $false
    }.GetNewClosure())
    
    $isB.Value.Add_Unchecked({
        $bu.Value.IsReadOnly = $true
        $bu.Value.Background = [System.Windows.Media.Brushes]::Gainsboro
    }.GetNewClosure())
    
    $isR.Value.Add_Checked({
        $isB.Value.IsChecked = $false
    }.GetNewClosure())
    

    I found this solution here.