前置き
最近ようやくWindowsフォームを脱却してWPFを勉強し始めてます。
そんな中で知った事について備忘録にまとめます。
また、情報を調べている際にChatGPTを使用しています。
本題
Windwosフォームでこういう画面をぺたぺた作ったとします。
当然これを起動してみるとこの通りの画面が表示されます。
対してWPF(xaml)で同じようにぺたぺた作ってみます。
<Window x:Class="ArduinoSerialReceiver.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ArduinoSerialReceiver"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button x:Name="Button" Content="Button" Margin="224,79,516,332" Click="Button_Click"/>
<ComboBox x:Name="ComboBox" Margin="98,79,599,332" Width="103"/>
<ListBox Margin="303,134,25,77" d:ItemsSource="{d:SampleData ItemCount=5}"/>
</Grid>
</Window>
各コンテンツを端からの距離で指定する形ですね。
Androidでもこういう指定の仕方あったなあとか思いながら作りました。
これを起動するとこうなります。
ボタンが見えねえ
コンボボックスも見えねえ
なんでお前(ListBox)だけ生き残った
原因
Button, ComboBoxが置かれている領域がGridだから。
あとMarginで位置指定してるから。
てきとうな解説
参考文献としてMicrosoftのドキュメントを確認してみましょう。
ほーんいろいろかいとるな。
xamlでの使い方もありますねえありますあります。
(以下抜粋)
<Grid ...>
oneOrMoreUIElements
</Grid>
-or-
<Grid .../>
ん?なんか見たことない表記部分あるな?
(以下一部抜粋)
<Grid x:Name="LayoutRoot" Background="#555555" Width="400" Height="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="2*" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
...
</Grid>
</Grid>
何やらColumnDefinition(列定義)とかRowDefinition(行定義)とか書かれてますね。
そうです。
GridはGridで位置を決めるものなんです。(あたりまえ)
変な描画になったやつではMerginで位置を指定させていましたがそれもそのはず。
これだと列も行も定義していないよく判らん領域にようわからん距離を置いてるコンテンツという意味で読まれてしまうんですね。
その結果、小さいMarginしかとっていないListBoxは描画され、他2つは小さく表示されるどころかつぶれて見えなくなってしまったということです。かわいそ。
解決策
Canvasを使ったら意図したていで行えるらしいですが、初期作成時にGridで指定されるのでそれならばと改めてGridでの作り方を確認しました。
<Window x:Class="ArduinoSerialReceiver.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ArduinoSerialReceiver"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="Button" Content="Connect"
Grid.Row="0" Grid.Column="0" Margin="5" Width="80" Height="30"/>
<ComboBox x:Name="portcomboBox"
Grid.Row="0" Grid.Column="1" Margin="5" Width="100"/>
<ListBox Grid.Row="1" Grid.ColumnSpan="2" Margin="5"/>
</Grid>
</Window>
なんかみためいい感じでいいですね(語彙力)
列・行の定義をして各コンテンツにもどの列・行なのかを設定しました。
WPFからはこういう変化に強いレイアウトを作る様にしたらいいということが判りました。
結論
WPFからはぺたぺた張るだけじゃだめだぞ!
余談
仕方がないことではあるのですが、XAMLへ直に書いていくのは結構勇気がいるので、なんかいい感じに右側のタブに列・行定義の窓を作ってほしいなあと思ったり思わなんだり。
WinUIならこのへんもいいかんじになってるのかなあ。



