記事を作っておきながら時間が経ちました。
今回はPowerShellでWPFの第二弾記事です。 前回の記事はこちら
PowerShellでWPFしたい Part1 – WPK編
さてPowerShell 3.0では、実はなんちゃってXAMLも書けちゃいます。 なんちゃってなのは、私が未熟なだけですが…とにかくWinFormsなんかと比べるなってぐらい扱いが楽です。 前回のWPKとは一風趣が変わりますがよろしければ… ====
Xaml実行にはとりあえず何が必要?
まずは、Add-Typeでpresentationframeworkを読み込みが必須です。
Add-Type -AssemblyName presentationframework
続いてXAML本文ですね!
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Test XAML / Show System Time" FontFamily="consolas" Height="350" Width="400" Margin="5" > <StackPanel> <Button Name="buttonGet" Content="Click me to show System time!!" FontSize="20" Height="60" Margin="5" /> </StackPanel> </Window>
System.Xml.XmlNodeReaderでxamlを読み込んで…!
$reader=(New-Object System.Xml.XmlNodeReader $xaml) $window=[Windows.Markup.XamlReader]::Load( $reader )
コントロールを探して…。
$buttonGet = $window.FindName("buttonGet")
イベント動作を記述します。
$buttonGet_clicked = $buttonGet.add_Click $buttonGet_clicked.Invoke({ $textboxTime.Text = Get-Date -Format "yyyy/MM/dd hh:mm:ss" })
簡単ですね!
サンプル
サクッと簡単にやってみます。
- buttonコントロールを押すとTextBoxに現在時刻が表示
- ListBoxにはItem aとItem bを追加
- OKを推すと、XAMLで描いた画面が終了
- 終了時にTextBoxに入力されている時刻、選択されているListBoxアイテムがPowershellにオブジェクトとして帰ってくる
ではサンプルを順番に見てみます。 XAMLを書いて変数に入れておきます。
$loadXaml =@' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Test XAML / Show System Time" FontFamily="consolas" Height="350" Width="400" Margin="5" > <StackPanel> <Button Name="buttonGet" Content="Click me to show System time!!" FontSize="20" Height="60" Margin="5" /> <Label Name="textboxLabel" Content="↓ System Time ↓" FontSize="15" Height="30" Margin="3" HorizontalAlignment="Center" /> <TextBox Name="textboxTime" Text="" FontSize="20" Background="#00AA88" Height="25" Margin="5" /> <ListBox Name="listbox" FontSize="20" Background="#AAAA88" Height="60" Margin="5" SelectionMode="Single" /> <Button Name="buttonOK" Content="OK" FontSize="14" Foreground="#FFFFFF" Background="#505050" Height="40" Margin="5" /> </StackPanel> </Window> '@
続いて、Xamlに対応する要素を制御するためのfunctionをツラツラっと
function Show-XAMLSystemTime{ [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = "none", DefaultParameterSetName = "" )] param ( [Parameter( HelpMessage = "Load binding Xaml you defined beforehands", Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [string] $loadXaml, [Alias("PassThru")] [switch] $PassThrough ) begin { try { # Add-Typeでアセンブリをロードする Add-Type -AssemblyName presentationframework } catch { #Alread Type added. } try { [xml]$xaml = $loadXaml } catch { } } process { $reader=(New-Object System.Xml.XmlNodeReader $xaml) $window=[Windows.Markup.XamlReader]::Load( $reader ) $buttonGet = $window.FindName("buttonGet") $textboxTime = $window.FindName("textboxTime") $listBoxItem = $window.FindName("listbox") $buttonOK = $window.FindName("buttonOK") #buttonGet event to show current datetime $buttonGet_clicked = $buttonGet.add_Click $buttonGet_clicked.Invoke({ $textboxTime.Text = Get-Date -Format "yyyy/MM/dd hh:mm:ss" }) #ListBox event [void]$listBoxItem.Items.Add("Item a") [void]$listBoxItem.Items.Add("Item b") #buttonOK event to close window $buttonOK_clicked = $buttonOK.add_Click $buttonOK_clicked.Invoke({ $Window.close()}) } end { $window.ShowDialog() | out-null #return to Powershell return [PSCustomObject]@{ time=$textboxTime.Text; listItem=$listboxItem.SelectedItem } } }
あとは、Xamlをfunctionに渡して実行します。
Show-XAMLSystemTime -loadXaml $loadXaml
ででーんと、XAMLが読み込まれ、このような画面が現れます。
Buttonをクリックすると…TextBoxに時間が表示されます。 ListBox Itemもハイライト選択できますね。
OKで完了すると、PowerShellホストにオブジェクトが返ってきます。
time listItem ---- -------- 2013/03/15 04:23:27 Item a
勿論、funtion実行時に変数へ代入しておけば後から再利用もできますね!
$WPFresult = Show-XAMLSystemTime -loadXaml $loadXaml $WPFresult $WPFresult.listItem $WPFresult.time
キッチリ変数に入ってますね。
time listItem ---- -------- 2013/03/15 04:23:27 Item a Item a 2013/03/15 04:23:27
まとめ
どうでしょうか。 WPKや次回のShow-UIに比べるとPowerShellらしくない = パイプを多用する記述ではありませんね。
ただ、プロパティにアクセスしてコントロールするのは楽です。 個人的には、結構好きですよ!ざむるざむる
おまけ : コード全文
function Show-XAMLSystemTime{ [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = "none", DefaultParameterSetName = "" )] param ( [Parameter( HelpMessage = "Enter tbind xaml @`...`@ to load.", Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [string] $loadXaml, ) begin { try { # Add-Typeでアセンブリをロードする Add-Type -AssemblyName presentationframework } catch { #Alread Type added. } try { [xml]$xaml = $loadXaml } catch { } } process { $reader=(New-Object System.Xml.XmlNodeReader $xaml) $window=[Windows.Markup.XamlReader]::Load( $reader ) $buttonGet = $window.FindName("buttonGet") $textboxTime = $window.FindName("textboxTime") $listBoxItem = $window.FindName("listbox") $buttonOK = $window.FindName("buttonOK") #buttonGet event to show current datetime $buttonGet_clicked = $buttonGet.add_Click $buttonGet_clicked.Invoke({ $textboxTime.Text = Get-Date -Format "yyyy/MM/dd hh:mm:ss" }) #ListBox event [void]$listBoxItem.Items.Add("Item a") [void]$listBoxItem.Items.Add("Item b") #buttonOK event to close window $buttonOK_clicked = $buttonOK.add_Click $buttonOK_clicked.Invoke({ $Window.close()}) } end { $window.ShowDialog() | out-null #return to Powershell return [PSCustomObject]@{ time=$textboxTime.Text; listItem=$listboxItem.SelectedItem } } } $loadXaml =@' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Test XAML / Show System Time" FontFamily="consolas" Height="350" Width="400" Margin="5" > <StackPanel> <Button Name="buttonGet" Content="Click me to show System time!!" FontSize="20" Height="60" Margin="5" /> <Label Name="textboxLabel" Content="↓ System Time ↓" FontSize="15" Height="30" Margin="3" HorizontalAlignment="Center" /> <TextBox Name="textboxTime" Text="" FontSize="20" Background="#00AA88" Height="25" Margin="5" /> <ListBox Name="listbox" FontSize="20" Background="#AAAA88" Height="60" Margin="5" SelectionMode="Single" /> <Button Name="buttonOK" Content="OK" FontSize="14" Foreground="#FFFFFF" Background="#505050" Height="40" Margin="5" /> </StackPanel> </Window> '@ $WPFresult = Show-XAMLSystemTime -loadXaml $loadXaml $WPFresult $WPFresult.listItem $WPFresult.time