PoshCode Archive  Artifact Content

Artifact 316790a6d8d60d4857d95c5260267f9977caded4715555b72ccd39be2122fe3e:

  • File Sj-strand.ps1 — part of check-in [533157f16d] at 2018-06-10 14:12:58 on branch trunk — wpftools is a tool for easy use of wpf (user: David size: 8210)

# encoding: utf-8
# api: powershell
# title: Sjöstrand
# description: wpftools is a tool for easy use of wpf
# version: 0.1
# type: function
# author: David
# license: CC0
# function: Get-WindowsClasses
# x-poshcode-id: 6316
# x-archived: 2016-04-24T06:47:14
# x-published: 2016-04-22T10:37:00
#
#
#Requires -Version 3
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
Add-Type –AssemblyName WindowsBase

function Get-WindowsClasses
{
    $exportedClasses = [System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework').ExportedTypes
	$exportedClasses += [System.Reflection.Assembly]::LoadWithPartialName('PresentationCore').ExportedTypes
	$exportedControlClasses = $exportedClasses | Where-Object {$_.isclass -and $_.fullname -like "System.Windows.*"}
	
	$controlClasses = @{}
	foreach ($controlClass in $exportedControlClasses)
	{
		$controlClasses[$controlClass.Name] = $controlClass.FullName
	} 
	$controlClasses
}

function Show-WpfWindow ([string]$XamlPath=".\MainWindow.xaml", [string]$HashTableName, [switch]$Dialog = $true)
{	
	if (!(Test-Path $XamlPath))
	{
		throw "Could not find file $XamlPath"
	}
    [xml]$xaml = Get-Content $XamlPath
	$nsmgr = new-object system.xml.xmlnamespacemanager($xaml.nametable)
	$nsmgr.AddNamespace("x",$xaml.DocumentElement.x)
	$xaml.window.RemoveAttribute("x:Class")
	$controlEvents = @{}
	$controlClasses = Get-WindowsClasses
	:outer foreach ($element in $xaml.SelectNodes('//*[@x:Name]', $nsmgr))
	{
	    $name = $element.name
	    $typename = $controlClasses[$element.LocalName]
	    $type = $null
	    try { $type = [type]$typename } catch { Write-Debug "type $typename does not exist"; continue outer}
	    Write-Debug "$typeName`: $name"
	    foreach ($event in $type.GetEvents())
	    {
	        $attributeName = $event.Name
	        $attributeValue = $element.GetAttribute($attributeName)
	        
		    if ($attributeValue -and (Test-Path "function:$attributeValue"))
	        {
                Write-Debug "Found event: $attributeName - $attributeValue"
	            $controlEvents[$name] += @{$attributeName=(Get-Item "function:$attributeValue").ScriptBlock}
	        }
		    elseif (Test-Path "function:${name}_$attributeName")
		    {
                Write-Debug "Found eventhandler $name_$attributeName"
	            $controlEvents[$name] += @{$attributeName=(Get-Item "function:${name}_$attributeName").ScriptBlock}
		    }
		    if ($AttributeValue)
		    {
			    $element.RemoveAttribute($attributeName)
		    }
	    }
	    
	}
	
	$reader = New-Object System.Xml.XmlNodeReader($xaml)
	$Window = [Windows.Markup.XamlReader]::Load( $reader )
    if ($PSBoundParameters.ContainsKey("HashTableName"))
    {
        if (Test-Path "Variable:$HashTableName")
        {
            Remove-Variable $HashTableName
        }

        $HashTable = (New-Variable -scope 1 -name $HashTableName -value ([hashtable]::Synchronized(@{})) -PassThru -Option Constant).Value
    }
            
	foreach ($element in $xaml.SelectNodes('//*[@x:Name]', $nsmgr))
	{
	    $name = $element.name
	    $control = $Window.FindName($name)
	
	    if ($control)
	    {
            if ($PSBoundParameters.ContainsKey("HashTableName"))
            {
                $HashTable[$name] = $control
            }
            else
            {
                if (Test-Path "Variable:$name")
                {
                    Remove-Variable $name
                }
	            New-Variable -scope 1 -Name $name -Value $control -Option Constant -ErrorAction SilentlyContinue
            }
	    }
	}
	
	foreach ($controlName in $controlEvents.Keys)
	{
	    $control = $Window.FindName($controlName)
	    if (!$control)
	    {
	        continue
	    }
	    foreach ($eventName in $controlEvents[$controlName].Keys)
	    {
	        #$scriptBlock = [System.Management.Automation.ScriptBlock]::Create($controlEvents[$controlName][$eventName])
	        $scriptBlock = $controlEvents[$controlName][$eventName]
            Write-Debug "Regestering event $controlname.${eventName}"
	        ($control."add_$eventName").Invoke($scriptBlock)
	    }
	}
    if ($Dialog)
    {
	    [void]$Window.ShowDialog()
    }
    else
    {
        [void]$Window.Show()
    }
}

function Get-WpfSnippet ($XamlPath=".\MainWindow.xaml", [string]$HashTableName,
	[parameter()]
	[ValidateSet("None", "Normal", "High", "Full")]
	[String[]]
	$CommentDetail="Normal",
	$CommentBorderLength = 85)
{
    if ([System.Management.Automation.Runspaces.Runspace]::DefaultRunspace.apartmentstate -ne "STA")
	{
        throw "Generate-WpfSnippet must be run in a single threaded apartment. Start PowerShell with the -STA flag and rerun the script."
        exit
    }

	[xml]$xaml = Get-Content $XamlPath
	$nsmgr = new-object system.xml.xmlnamespacemanager($xaml.nametable)
	$nsmgr.AddNamespace('x',$xaml.DocumentElement.x)
	#$xaml.window.RemoveAttribute("x:Class")
        if ($CommentDetail -ne 'None')
        {
	    '#' * $CommentBorderLength
	    '# Controls:'
	    '#'
        }

	$controlEvents = @{}
	$controlTypes = @{}
	$controlClasses = Get-WindowsClasses
	:outer foreach ($element in $xaml.SelectNodes('//*[@x:Name]', $nsmgr))
	{
	    $name = $element.name
	    $typename = $controlClasses[$element.LocalName]
	    Write-Debug "$typeName`: $name"
	    $type = $null
        if ($controlTypes.ContainsKey($typename))
        {
            $type = $controlTypes[$typename]
        }
        else
        {
	        try { $type = [type]$typename } catch { Write-Debug "Unknown error getting type $typename"; continue outer}
            $controlTypes[$typename] = $type
        }
        
        if ($CommentDetail -ne 'None')
        {
            if ($PSBoundParameters.ContainsKey("HashTableName"))
            {
                '#  ${0}{1,-20} ({2})' -F $HashTableName,"['$name']",$typename
            }
            else
            {
                '#  ${0,-20} ({1})' -F $name,$typename
            }
	    }
	    foreach ($event in $type.GetEvents())
	    {
	        $attributeName = $event.Name
	        $attributeValue = $element.GetAttribute($attributeName)
		    if ($attributeValue)
	        {
	            Write-Debug "Found event handler: $attributeName - $attributeValue"
	            $controlEvents[$attributeValue] += @{$name=$attributeName}
	            #$element.RemoveAttribute($attributeName)
	        }
	    }
	    
	}
    if ("High","Full" -contains $CommentDetail)
    {
	    '#' * $CommentBorderLength
	    '# Types:'
	    '#'
	    foreach ($typename in $controlTypes.Keys)
	    {
	        "# $typename"
            $str = '#     Events:'
		    $count = 0
            foreach ($eventName in ($controlTypes[$typename].GetEvents() | Select-Object -ExpandProperty Name))
            {
                if (!($count++ % 3))
                {
                    $str += "`n#      "
                }
                $str += "$eventName ".PadRight(30)
            }
		    $str.Split("`n")
		    if ($CommentDetail -ne "Full")
		    {
		        continue
            }
            "#     Properties:"
            foreach ($Property in $controlTypes[$typename].GetProperties())
            {
                '#      {0,-30} ({1})' -F $property.name,$property.propertyType.fullname
            }

        }
    } 
    if ($CommentDetail -ne 'None')
    {
	    '#'
	    '#' * $CommentBorderLength
            ''
    }
    '#Requires -Version 2'
    '. .\wpftools.ps1'
	''
	'# Event handlers:'
	''
	foreach ($eventName in $controlEvents.Keys)
	{
	    foreach ($controlName in $controlEvents[$eventName].Keys)
	    {
	        "# $controlName $($controlevents[$eventName][$controlName])"
        }
	    "function $eventName"
        '{'
        '}'
        ''	    
	}
	
    if ($PSBoundParameters.ContainsKey("HashTableName"))
    {
        "Show-WpfWindow -XamlPath '$XamlPath' -HashTableName '$HashTableName'"
    }
    else
    {
	    "Show-WpfWindow -XamlPath '$XamlPath'"
    }
}