functions/ConvertTo-WPFGrid.ps1




Function ConvertTo-WPFGrid {

    [cmdletbinding()]
    [Alias("cwg")]
    [outputtype("none")]

    Param(
        [Parameter(ValueFromPipeline)]
        [psobject]$InputObject,
        [string]$Title = "ConvertTo-WPFGrid",
        [ValidateScript( {$_ -ge 5})]
        [int]$Timeout,
        [switch]$Refresh
    )

    Begin {

        Write-Verbose "Starting $($MyInvocation.MyCommand)"

        if ($Refresh -AND $timeout -le 5) {
            Throw "You must specify a timeout value when using -Refresh"
        }

        Write-Verbose "Starting $($MyInvocation.MyCommand)"
        Write-Verbose "Creating new runspace"
        $newRunspace = [RunspaceFactory]::CreateRunspace()
        $newRunspace.ApartmentState = "STA"
        $newRunspace.ThreadOptions = "ReuseThread"
        $newRunspace.Open()
        Write-Verbose "Defining script command"
        $psCmd = [PowerShell]::Create().AddScript( {
                Param(
                    [string]$Title = "ConvertTo-WPFGrid",
                    [ValidateScript( {$_ -ge 5})]
                    [int]$Timeout = 0,
                    [switch]$CenterScreen,
                    [object[]]$Data,
                    [scriptblock]$cmd,
                    [switch]$Refresh
                )
                # It may not be necessary to add these types but it doesn't hurt to include them
                Add-Type -AssemblyName PresentationFramework
                Add-Type -AssemblyName PresentationCore
                Add-Type -AssemblyName WindowsBase

                $form = New-Object System.Windows.Window
                $form.Title = $Title

                #define a handler when the form is loaded. The scriptblock uses variables defined later
                #in the script
                $form.add_Loaded( {
                        foreach ($col in $datagrid.Columns) {
                            #because of the way I am loading data into the grid
                            #it appears I need to set the sorting on each column
                            $col.CanUserSort = $True
                            $col.SortMemberPath = $col.Header
                        }

                        $form.Height = $datagrid.actualHeight + $status.actualHeight + 50
                        $form.width = $datagrid.actualwidth + 50

                        $datagrid.Items.Refresh()
                        $status.Width = $datagrid.ActualWidth
                        If ($Timeout -gt 0) {
                            $timer.IsEnabled = $True
                            $Timer.Start()
                        }

                        $form.UpdateLayout()
                        $form.focus
                    })

                $Form.Add_closing( {
                        #reserved for future use
                    })
                $Form.Add_closed( {
                        #reserved for future use
                    })
                #Create a stack panel to hold the datagrid
                $stack = New-Object System.Windows.Controls.StackPanel
                $stack.HorizontalAlignment = "center"

                #create a datagrid
                $datagrid = New-Object System.Windows.Controls.DataGrid
                $datagrid.VerticalAlignment = "top"
                $datagrid.HorizontalAlignment = "center"
                $datagrid.ColumnWidth = "Auto"
                #autosize the datagrid
                $datagrid.Height = "Auto"
                $datagrid.Width = "Auto"
                $datagrid.CanUserSortColumns = $True
                $datagrid.CanUserResizeColumns = $True
                $datagrid.CanUserReorderColumns = $True
                $datagrid.AutoGenerateColumns = $True
                #enable alternating color rows
                $datagrid.AlternatingRowBackground = "gainsboro"
                $datagrid.ItemsSource = $data

                $stack.AddChild($datagrid)

                $status = New-Object System.Windows.Controls.TextBlock
                $status.Height = 20
                $status.Background = "lightgray"
                $status.VerticalAlignment = "top"
                $status.HorizontalAlignment = "center"

                $stack.AddChild($status)

                $form.AddChild($stack)

                $Now = Get-Date
                # define a timer to automatically dismiss the form. The timer uses a 1 second interval tick
                if ($Timeout -gt 0) {
                    [int]$script:count = $Timeout
                    $timer = New-Object System.Windows.Threading.DispatcherTimer
                    [datetime]$script:terminate = $now.AddSeconds($timeout)
                    $timer.Interval = [TimeSpan]"0:0:1.00"

                    $timer.add_tick( {
                            if ((Get-Date) -lt $script:terminate) {
                                $status.text = " Last updated $Now - refresh in $script:count seconds"
                                $status.UpdateLayout()
                                $script:count--
                            }
                            else {
                                $timer.stop()
                                if ($Refresh) {
                                    $datagrid.itemssource = Invoke-Command -ScriptBlock $cmd
                                    $datagrid.items.refresh()
                                    $script:count = $timeout
                                    $now = Get-Date
                                    [datetime]$script:terminate = $now.AddSeconds($timeout)
                                    $status.text = " Last updated $Now - refresh in $script:count seconds"
                                    $status.UpdateLayout()
                                    $Timer.Start()
                                }
                            }
                        })
                }
                else {
                    $status.text = " last updated $Now"
                }

                $form.ShowDialog()
            })

        #initialize an array to hold all processed objects
        $data = @()
    } #begin

    Process {
        #add each incoming object to the data array
        $data += $Inputobject
    } #process

    End {
        Write-Verbose "Updating PSBoundparameters"
        $PSBoundParameters.Data = $data
        $PSBoundParameters.remove("Inputobject") | Out-Null
        #parse the invocation to get the pipelined expression up to this command
        $cmd = [scriptblock]::Create($myinvocation.line.substring(0, $myinvocation.line.LastIndexOf("|")))
        $psboundparameters.cmd =$cmd
        Write-Verbose "Refresh command: $cmd"
        Write-Verbose "Sending PSBoundparameters to runspace"
        $psCmd.AddParameters($PSBoundParameters) | Out-Null

        $psCmd.Runspace = $newRunspace
        Write-Verbose "Begin Invoke()"
        $psCmd.BeginInvoke() | Out-Null

        Write-Verbose "Ending $($MyInvocation.MyCommand)"

    } #end

} #close function