PowerShellでGUI: 部品配置はGridとテキスト編集が良い
2つ前の記事「PowerShellでGUI: 可変個数RadioButton実現方法(別法) - Itsukaraの日記」で、PowerShellのGUIをVisual Studioで作成する方法を書きました。ただ、GUIを実現するWPFの勉強が不足していたので、GUI画面上にGUI部品を適当に貼り付けていました。そのため、部品の位置等を表す数字「Margin="68,119,0,0"」が沢山あり、後で調整するのが大変そうと感じました。
その後、WPFを少し調べたところ、GRIDを使うことにより部品をテーブル状に整然と並べることが出来ると分かりました。下記のような感じです。
ただ、GRIDへのGUI部品配置をGUIでやると、微調整が結構面倒なので、1~2個部品を並べたら、あとは、XAMLテキストをコピー・ペーストし適切な修正を行うのが良いです。
また、GUIで部品を配置すると、HeightやMarginなどに、色々な数字が入りますが、これらが部品ごとに入っていると、後で纏めて変えるのが面倒なので、それらの数字はできるだけ削っておいた方が良いです。順序としては、上記のコピー・ペーストの前にやっておく必要がありますね。
なお、Syleを使うと、後でTextBoxのHeightを纏めて30にしたりといったことが、簡単にできます。Styleは、<Window.Resources>というタグ内に記述します。
結果として、次のようなプログラムになりました。表示内容は、依然とあまり変わりませんが、無駄な数字がなくなって、すっきりしています。その分、後で変更するのが楽(なはず)です。
- プログラム例-
$ErrorActionPreference = "stop" Set-PSDebug -Strict Add-Type -AssemblyName PresentationFramework [xml]$xaml = @' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <Style TargetType="TextBox"> <Setter Property="Height" Value="30"/> </Style> <Style TargetType="Button"> <Setter Property="Height" Value="30"/> </Style> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Blue"/> </Style> </Window.Resources> <Grid Margin="10,10,10,10"> <Grid.RowDefinitions> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="10"/> <RowDefinition Height="30"/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Label x:Name="label01" Content="名前" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Right"/> <TextBox x:Name="textName" Margin="0" TextWrapping="Wrap" VerticalAlignment="Center" Grid.Column="1"/> <Label x:Name="label02" Content="ふりがな" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Row="1"/> <TextBox x:Name="textFurigana" Margin="0" TextWrapping="Wrap" VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" /> <Label x:Name="label03" Content="性別" Margin="0" VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Row="2"/> <StackPanel x:Name="stackGender" HorizontalAlignment="Left" Margin="0" VerticalAlignment="Center" Orientation="Horizontal" Grid.Column="1" Grid.Row="2" Width="120"> <RadioButton x:Name="radioButtonMale" Content="Male" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,10,0"/> <RadioButton x:Name="radioButtonFemale" Content="Female" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0"/> </StackPanel> <Label x:Name="label04" Content="国籍" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Row="3"/> <ComboBox x:Name="comboBoxCountry" HorizontalAlignment="Left" Margin="0" VerticalAlignment="Center" Grid.Row="3" Grid.Column="1" Width="100"/> <Label x:Name="label05" Content="年齢" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Row="4"/> <TextBox x:Name="textAge" Margin="0" TextWrapping="Wrap" VerticalAlignment="Center" Grid.Column="1" Grid.Row="4" Width="50" HorizontalAlignment="Left" /> <Button x:Name="buttonRegist" Content="登録" Margin="0" VerticalAlignment="Center" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="6" /> <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="0" TextWrapping="Wrap" VerticalAlignment="Top" Grid.ColumnSpan="2" Grid.Row="7"/> </Grid> </Window> '@ $reader = New-Object System.Xml.XmlNodeReader $xaml $frm = [System.Windows.Markup.XamlReader]::Load($reader) $countries = "U.S.A China Japan Germany France England Russia".split(" ") $comboBoxCountry = $frm.FindName("comboBoxCountry") foreach ($country in $countries) { [void]$comboBoxCountry.Items.Add($country) } $textName = $frm.FindName("textName") $comboBoxCountry = $frm.FindName("comboBoxCountry") $textFurigana = $frm.FindName("textFurigana") $stackGender = $frm.FindName("stackGender") $textAge = $frm.FindName("textAge") $textBlock = $frm.FindName("textBlock") function getChecked($parent) { $checked = "" foreach ($child in $parent.Children) { if ($child.isChecked) { $checked += $child.Content } } return $checked } function regist { $name = $textName.Text $furigata = $textFurigana.Text $gender = getChecked $stackGender $country = $comboBoxCountry.SelectedValue $age = $textAge.Text $msg = "" $msg += "名前:" + $name + "`n" $msg += "ふりがな:" + $furigata + "`n" $msg += "性別:" + $gender + "`n" $msg += "国籍:" + $country + "`n" $msg += "年齢:" + $age + "`n" $textBlock.Text = $msg } $buttonRegist = $frm.FindName("buttonRegist") $buttonRegist.Add_Click({regist}) $result = $frm.ShowDialog()
- 画面表示例