CommonControls/Select-ViaUI.ps1

function Select-ViaUI {
#.Synopsis
# Select objects through a visual interface
#.Description
# Uses a graphical interface to select (and pass-through) pipeline objects
# Idea from Lee Holmes (http://www.leeholmes.com/blog)
#.Example
# Get-ChildItem | Select-ViaUI -show | Remove-Item -WhatIf
    [OutputType([Windows.Controls.Grid])]
    param(
    # The name of the control
    [string]$Name,
    # If the control is a child element of a Grid control (see New-Grid),
    # then the Row parameter will be used to determine where to place the
    # top of the control. Using the -Row parameter changes the
    # dependency property [Windows.Controls.Grid]::RowProperty
    [Int]$Row,
    # If the control is a child element of a Grid control (see New-Grid)
    # then the Column parameter will be used to determine where to place
    # the left of the control. Using the -Column parameter changes the
    # dependency property [Windows.Controls.Grid]::ColumnProperty
    [Int]$Column,
    # If the control is a child element of a Grid control (see New-Grid)
    # then the RowSpan parameter will be used to determine how many rows
    # in the grid the control will occupy. Using the -RowSpan parameter
    # changes the dependency property [Windows.Controls.Grid]::RowSpanProperty
    [Int]$RowSpan,
    # If the control is a child element of a Grid control (see New-Grid)
    # then the RowSpan parameter will be used to determine how many columns
    # in the grid the control will occupy. Using the -ColumnSpan parameter
    # changes the dependency property [Windows.Controls.Grid]::ColumnSpanProperty
    [Int]$ColumnSpan,
    # The -Width parameter will be used to set the width of the control
    [Int]$Width, 
    # The -Height parameter will be used to set the height of the control
    [Int]$Height,
    # If the control is a child element of a Canvas control (see New-Canvas),
    # then the Top parameter controls the top location within that canvas
    # Using the -Top parameter changes the dependency property
    # [Windows.Controls.Canvas]::TopProperty
    [Double]$Top,
    # If the control is a child element of a Canvas control (see New-Canvas),
    # then the Left parameter controls the left location within that canvas
    # Using the -Left parameter changes the dependency property
    # [Windows.Controls.Canvas]::LeftProperty
    [Double]$Left,
    # If the control is a child element of a Dock control (see New-Dock),
    # then the Dock parameter controls the dock style within that panel
    # Using the -Dock parameter changes the dependency property
    # [Windows.Controls.DockPanel]::DockProperty
    [Windows.Controls.Dock]$Dock,
    # If Show is set, then the UI will be displayed as a modal dialog within the current
    # thread. If the -Show and -AsJob parameters are omitted, then the control should be
    # output from the function
    [Switch]$Show,
    # If AsJob is set, then the UI will displayed within a WPF job.
    [Switch]$AsJob        
)


    # We're going to need the parameters later
    $uiParameters = @{} + $psBoundParameters

    # we need to store the original items ... so we can output them later
    # But we're going to convert them to strings to display them
    $SelectViaUIStringItems = New-Object System.Collections.ArrayList
    # So, use a hashtable, with the strings as the keys to the original values
    $Script:SelectViaUIOriginalItems = @{}
    ## Convert input to string representations and store ...
    foreach($item in $Input) {
        ## Get the item as it would be displayed by Format-Table
        $stringRepresentation = (($item | ft -HideTableHeaders | Out-String )-Split"\n")[-4].trimEnd()
        $SelectViaUIOriginalItems[$stringRepresentation] = $item
        $null = $SelectViaUIStringItems.Add($stringRepresentation)
    }

## Generate the window
# Show-UI -Title "Object Filter" -MinWidth 400 -Height 600 {
Grid -Margin 5  -ControlName SelectFTList -Rows Auto, *, Auto, Auto -Resource @{
    # The Resource dictionary is used to store information and default settings
    Cmdlet = $psCmdlet
    PSBoundParameters = $PSBoundParameters
    Args = $args
} -Children {
    ## This is just a label ...
    TextBlock -Margin 5 -Row 0 "Type or click to search. Press Enter or click OK to pass the items down the pipeline." 

    ## Put the items in a ListBox, inside a ScrollViewer so it can scroll :)
    ScrollViewer -Margin 5 -Row 1 {
        ListBox -SelectionMode Multiple -ItemsSource $SelectViaUIStringItems -Name SelectedItems  `
                -FontFamily "Consolas, Courier New"  -On_SelectionChanged {
                    $source = $selectedItems.Items
                    if($selectedItems.SelectedItems.Count -gt 0)
                    {
                        $source = $selectedItems.SelectedItems
                    }
                    $SelectFTList | Set-UIValue -value $SelectViaUIOriginalItems[$source]
                }
                # -On_MouseDoubleClick { Close-Control $parent }
    }

    ## This is the filter box: Notice we update the filter on_KeyUp
    TextBox -Margin 5 -Name SearchText -Row 2 -On_KeyUp {
        $filterText = $this.Text
        [System.Windows.Data.CollectionViewSource]::GetDefaultView( $SelectedItems.ItemsSource ).Filter = [Predicate[Object]]{ 
            param([string]$item)
            ## default to true
            trap { return $true }
            ## Do a regex match
            $item -match $filterText
        }
        
        ## Update the output after the filter
        $source = $selectedItems.Items
        if($selectedItems.SelectedItems.Count -gt 0)
        {
            $source = $selectedItems.SelectedItems
        }
        $SelectFTList | Set-UIValue -value $SelectViaUIOriginalItems[$source]
    }

    ## Use a GridPanel ... it's a simple, yet effective way to lay out a couple of buttons.
    Grid -Margin 5 -HorizontalAlignment Right -Columns 65, 10, 65 {
        Button "OK" -IsDefault -Width 65 -On_Click { Close-Control $window } -Column 0
        Button "Cancel" -IsCancel -Width 65 -On_Click { $SelectFTList | Set-UIValue -value $null } -Column 2
    } -Row 3
    ## Focus on the Search box by default
} -On_Loaded { 
    $SearchText.Focus()
    ## Default output, in case you close the window without selecting anything
    $SelectFTList | Set-UIValue -value $SelectViaUIOriginalItems[$selectedItems.Items]
} @uiParameters

}