public/list/New-UiMenuItem.ps1
|
function New-UiMenuItem { <# .SYNOPSIS Defines one entry for a data grid's right-click menu. .DESCRIPTION Builder for the -RowContextMenu parameter on New-UiDataGrid. Each call becomes one menu item; pass the calls inside a scriptblock or an array and the menu keeps their order. Emits a definition object only - it does not add anything to the window. The action runs with $_ bound to the clicked row. When the click lands inside a multi-selection, the action runs once per selected row. Equivalent to one entry of the legacy label-keyed hashtable form, which -RowContextMenu still accepts. .PARAMETER Text Menu item label. Labels must be unique within one menu (case-insensitive). .PARAMETER Action Scriptblock to run when the item is clicked. $_ is the target row. On multi-select the action reruns once per selected row. .PARAMETER Enabled $true, $false, or a scriptblock probed per row every time the menu opens ($_ = row). The item grays out when no targeted row passes. Probing caps at 20 rows on big selections; past that the item stays enabled and the click still skips ineligible rows. .PARAMETER Icon Icon name shown ahead of the label. Tab completion lists the valid names. .PARAMETER NoAsync Run the action on the UI thread instead of a background runspace. For actions that open dialogs or child windows. Accepts -Sync as an alias, the parameter this switch had used before. .EXAMPLE New-UiDataGrid -Variable 'svc' -Items (Get-Service) -RowContextMenu { New-UiMenuItem 'Start' -Icon Play -Action { Start-Service $_.Name } -Enabled { $_.Status -eq 'Stopped' } New-UiMenuItem 'Details' -NoAsync -Action { Show-UiMessageDialog -Message ($_ | Out-String) } } .EXAMPLE # Legacy hashtable form, still supported New-UiDataGrid -Variable 'svc' -Items (Get-Service) -RowContextMenu ([ordered]@{ 'Start' = @{ Action = { Start-Service $_.Name }; Enabled = { $_.Status -eq 'Stopped' } } 'Details' = @{ Action = { Show-UiMessageDialog -Message ($_ | Out-String) }; NoAsync = $true } }) #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [string]$Text, [Parameter(Mandatory, Position = 1)] [scriptblock]$Action, [object]$Enabled, [Alias('Sync')] [switch]$NoAsync ) DynamicParam { Get-IconDynamicParameter -ParameterName 'Icon' } begin { $Icon = $PSBoundParameters['Icon'] } process { # The menu builder casts a non-scriptblock Enabled straight to [bool], and 'false' casts truthy. Catch the type here where the error can name the right function. if ($null -ne $Enabled -and $Enabled -isnot [bool] -and $Enabled -isnot [scriptblock]) { throw "New-UiMenuItem: -Enabled takes `$true/`$false or a scriptblock. Got [$($Enabled.GetType().Name)]." } # Keys stay absent unless the parameter was bound. The consumer reads $null -ne Enabled, so absent and $false mean different things there. NoAsync stays conditional to match. $item = @{ Text = $Text; Action = $Action } if ($Icon) { $item['Icon'] = $Icon } if ($PSBoundParameters.ContainsKey('Enabled')) { $item['Enabled'] = $Enabled } if ($PSBoundParameters.ContainsKey('NoAsync')) { $item['NoAsync'] = [bool]$NoAsync } $item } } |