VB.NETでGUIアプリ入門（.NET Framework 4.x）

# ■はじめに

Visual Basic .NET（VB.NET）と.NET FrameworkでGUIアプリを作ってみます。

# ■環境

* Windows 10
* Visual Studio 2019 Community
* .NET Framework 4.8

# ■準備

Visual Studio 2019のコミュニティ版をダウンロードしてインストールします。

[Visual Studio 2019 for Windowsのダウンロード](https://visualstudio.microsoft.com/ja/downloads/)

インストールが終わったらVisual Studio Installerを起動し、`ワークロード`タブの`.NET デスクトップ開発`にチェックが入っていることを確認します。チェックが入っていなかったらチェックを入れてインストールします。
![vb001a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/97eab015-1d1a-dae4-6986-1a13c9960ef2.png)

# ■STEP1. 画面を表示する

## ◇1-1. プロジェクトの作成

Visual Studio 2019を起動します。
`新しいプロジェクトの作成`ボタンを押します。
![vb001b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/52962304-eec5-9ac9-2899-b6402e54098b.png)

右上のドロップダウンリストから`Visual Basic`, `Windows`, `デスクトップ`を選択して候補を絞り込み、
`WPFアプリ（.NET Framework）`を選択して`次へ`ボタンを押します。
![vb002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/66206e2d-c906-f8f9-ed38-eba127e468ef.png)

プロジェクト名を付けます。ここでは`GuiTest1`にしました。
フレームワークを選択します。ここでは4.8にしました。4.8が選択肢にない場合、なるべく新しいバージョン（4.5以上）を選択してください。
`作成`ボタンを押します。
![vb003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/c06bfeed-e9ab-28e3-d928-4c303a31bb97.png)

編集画面が表示されました。
![vb004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/d7631e43-4516-11d3-1913-37c0298d149e.png)

各エリアの名称と役割は以下の通りです。

* (1)ツールボックス
    * 配置できるコントロールが一覧表示されています。
* (2)デザイナー デザインエリア（以後「画面デザイナ」と表記）
    * 画面イメージです。
* (3)デザイナー XAMLエリア（以後「Xamlエディター」と表記）
    * 画面定義です。
* (4)ソリューションエクスプローラー
    * プログラムのファイル構成が表示されます。

そしてこれがコントロールの設定値（プロパティ）を編集するためのプロパティウィンドウです。

レイアウト例1)
![vb101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/9cf9f489-d01a-bbe6-ed4e-7330601bb69e.png)
レイアウト例2)
![vb102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/ba633adb-9ed7-5f53-7755-cb2d78991fa6.png)

これらが表示されていない場合、`表示`メニューから表示させてください。
![vb005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/d09c4a52-ad79-9733-9d19-8fbf8d3c0c95.png)

## ◇1-2. Visual Studioから実行

まずはいきなり実行してみます。
ツールバーの`開始`ボタンを押してください。
EXEファイルが作成され、プログラムが起動します。
![vb004b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/23679066-83d6-995c-42e4-92871e89f77f.png)

まっさらな画面が表示されました。
`×`ボタンで終了してください。
![vb004c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/1f036cff-7dab-7e0d-fcd7-c1ef765cd477.png)

## ◇1-3. 直接EXEを実行

さきほど実行したときにEXEが作られたので今度はエクスプローラーから直接実行してみます。
ソリューションエクスプローラーでプロジェクト`GuiTest1`を右クリックし、`エクスプローラーでフォルダを開く`を選択してください。
![vb004d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/98cd7cf1-323c-cbbe-c11a-194bde21cb6e.png)

エクスプローラーが起動するので `bin` → `Debug`とフォルダを開いていってください。
![vb004e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/d760f96a-a1fa-d9fe-909f-739adf4276b5.png)
　↓
![vb004f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/5aef53d4-63ac-46c6-6620-95760da844be.png)

`GuiTest1.exe`をダブルクリックしてください。
先ほどと同じ画面が表示されました。
`×`ボタンで閉じてください。
![vb004g.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/6231b11d-d485-3ad9-7490-ff84a17a2e64.png)

# ■STEP2. StackPanelとボタン

次はボタンをいくつか配置してみます。

## ◇2-1. 土台をGridからStackPanelに変更

コントロールを配置する前に、土台となる部分をGridからStackPanelに変更します。
画面デザイナ中のウィンドウの白い部分（Grid）で右クリックし、`レイアウトの種類の変更` - `StackPanel`を選択します。
![vb100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/cfef44fc-b6ff-d665-fe36-09550e016f94.png)

画面デザイナ上では見た目の変化はありませんが、Xamlエディターの`Grid`タグが`StackPanel`タグに変わりました。
ツールボックスから`Button`を`StackPanel`にドラッグ＆ドロップします。
![vb101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/b32bcde0-9b08-e786-9db8-276da4a006d8.png)

## ◇2-2. ボタン配置

`Button`が追加されました。
位置やサイズを指定しなくても自動的に上端に配置されます。
引き続き、追加で2つボタンをドラッグ＆ドロップします。
![vb102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/b9efcd74-0f2f-c9d8-bb45-0e64f155271a.png)

積み重なるようにButtonが配置されました。
これがStackPanelの機能です。
![vb103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/ba56dc69-b978-5a24-b48e-a2d67f588cd0.png)

## ◇2-3. ボタンのプロパティ変更

真ん中の`Button`を選択し、プロパティウィンドウで`共通` - `Content`プロパティに`ぼたん`と入力して<kbd><kbd>Enter</kbd></kbd>してください。
画面デザイナのボタンテキストとXamlエディターに反映されます。
![vb104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/4c065543-e358-1c5c-8fe6-a59d1011678d.png)

一番下の`Button`を選択し、プロパティウィンドウで`ブラシ` - `Background`プロパティを選択し、右端の`ブラシリソース`タブを選択、`InfoBrushKey`を選択します。
これでボタン背景色が変わります。
![vb105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/65a49461-46d6-0957-4eb6-8f41f27b0075.png)

## ◇2-4. ボタンクリック処理の作成

一番上のボタンをダブルクリックします。
![vb106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/b3f80e24-361c-14fc-8949-5bd3ef40e147.png)

自動的にコードエディタに移動します。
`MainWindow.xaml`のタブがデザイナー、`MainWindow.xaml.vb`のタブがコードです。
![vb107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/dad3e6cf-3743-f0db-dbea-11d3792fa6d6.png)

メッセージボックスを表示するコードを書きます。

```vb:MainWindow.xaml.vb
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    MessageBox.Show("こんにちは")
End Sub
```

## ◇2-5. 実行

ここまで作成したら`開始`ボタンを押して実行してみます。
![vb108.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/de8e1a44-1c61-fc30-7cfe-97372bc723e6.png)

一番上のボタンを押すとメッセージボックスが表示されます。
![vb109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/565c9369-887d-3c9e-32ea-81cfdc69c869.png)

メッセージボックスと画面を閉じてください。

## ◇2-6. 共通ボタン処理

次は別の方法でボタンクリック時の処理を作ります。
画面デザイナで真ん中のボタンを選択し、プロパティウィンドウの稲妻マークを選択してください。
ボタンに設定できるイベントの一覧が出てきます。
（プロパティの一覧に戻るには、稲妻マークの左にある工具のマークをクリックしてください）
![vb110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/14b6e6c9-dc06-9aa9-f7e2-ae9f10037e21.png)

`Click`イベントに`ボタンクリック共通処理`と入力して<kbd><kbd>Enter</kbd></kbd>してください。
![vb110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/38501099-0344-c974-42f9-792943c7d4ea.png)

コードを以下のように書いてください。
`'`から始まる行はコメントです。

```vb:MainWindow.xaml.vb
Private Sub ボタンクリック共通処理(sender As Object, e As RoutedEventArgs)
    ' 押されたボタンのテキストをタイトルバーに表示
    Me.Title = CType(sender, Button).Content & "が押されました。"
End Sub
```

引数のsenderには押したボタンが渡されるので、そのボタンのテキスト（Content）をウィンドウのタイトルバーに表示します。

`MainWindow.xaml`のタブを選択してデザイナーに戻り、
真ん中のボタンに設定したClickイベントの `ボタンクリック共通処理`の文字列をコピーし、
一番下のボタンを選択し、Clickイベントに貼り付けて<kbd><kbd>Enter</kbd></kbd>してください。
![vb111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/3e7ddccc-72df-359d-d535-e092f8d83361.png)

ここまででXamlのStackPanel配下は以下のようになっているはずです。
（見やすいように改行を入れています）

```Xml:MainWindow.xaml
<StackPanel>
    <Button 
        Content="Button" 
        Click="Button_Click"/>
    <Button 
        Content="ぼたん" 
        Click="ボタンクリック共通処理"/>
    <Button 
        Content="Button" 
        Background="{DynamicResource {x:Static SystemColors.InfoBrushKey}}" 
        Click="ボタンクリック共通処理"/>
</StackPanel>
```

## ◇2-7. 実行

実行してみます。
`開始`ボタンを押し、画面が表示されたら真ん中のボタンを押します。
![vb112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/9374b614-8470-83da-7ab5-9828effc02ae.png)

次は一番下のボタンを押してみます。
![vb113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/a5dcd174-086f-0cc8-ccbd-7b67bd514411.png)

1つのボタンクリック処理を2つのボタンで利用しました。

# ■STEP3. 別画面表示

別の画面を表示する処理を作ってみます。

## ◇3-1. 画面追加

ソリューションエクスプローラーの`GuiTest1`プロジェクトを右クリック、`追加` - `ウィンドウ`を選択します。
![vb201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/8c1b397f-c7be-fd26-b649-20a4c52a2558.png)

名前に`Window1.xaml`が指定されているのでそのまま`追加`ボタンを押します。
![vb202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/b1f127d7-eed7-d5f8-fc1a-d43fd52ea444.png)

新しい画面が追加されました。
![vb203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/38762072-2519-1370-cdac-6712d0be875c.png)

## ◇3-2. 画面表示処理作成

`MainWindow.xaml`タブを選択します。
`Button`を新たに追加し、`Content`プロパティに`画面表示`を設定します。
![vb204.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/57247413-d22e-c13a-428b-9cf122052c52.png)

稲妻マークを選択し、`Click`のテキストボックス内をダブルクリックします。
![vb205.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/250e11ce-a626-72ea-74d4-934b36562c55.png)

コードエディタに移動するので先ほど追加した`Window1`を生成して表示する処理を書きます。

```vb:MainWindow.xaml.vb
Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
    Dim window = New Window1()
    window.ShowDialog()
End Sub
```

## ◇3-3. 実行

実行してみます。
`画面表示`ボタンを押すと`Window1`が表示されました。
![vb206.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/30889a0d-0fd3-978e-3737-ea226a261bb1.png)


# ■STEP4. Gridと計算

次はGridを使ってみます。

## ◇4-1. Grid分割

まずは画面のGridを以下のように分割します。
![vb026b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/6c6ae4b4-9886-4406-49ff-eda678f4e1e2.png)

画面デザイナでGridを選択した状態で下図の赤く塗ったあたりにマウスカーソルを持っていくと`+`マークが付きます。
![vb301.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/756a8aac-330b-f5fb-499c-1085631cdee1.png)

マウスカーソルが変わったらクリックします。
![vb302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/fdaf4abe-7439-45e1-ef05-42203e4455b4.png)

分割されました。
![vb303.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/9f7992f2-99d4-8f5e-4116-3ccd0794231e.png)

もう一列分も分割します。
![vb304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/953eadbf-f190-7936-216c-a3dde7400f47.png)

横も分割します。
![vb305.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/0e7bb36f-12cc-03a3-49c3-d84df5a1a3fb.png)

![vb306.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/33ed3211-b49c-9a23-63fa-8e504d45a149.png)

## ◇4-2. 分割サイズ変更

分割の割合を調整します。
(1)で囲ったあたりにマウスカーソルをポイントします。
(2)の数字部分に`1*`を入力します。
![vb307.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/f3aa81fd-fe72-1780-c3e6-8858419d4469.png)

1列目が見えなくなりましたが、気にせず2列目に`2*`を入力します。
![vb308.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/e261fd89-b6fc-bdc9-2faa-c96bade869df.png)

3列目に`3*`を入力します。
1行目に`1*`を入力します。
![vb309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/0984608f-fb6d-3a74-edee-8beb26d3a43e.png)

2行目に`4*`を入力します。
![vb310.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/78dd922e-9934-14ee-cab5-3f6d8bdcd450.png)

`2*`は`1*`の2倍のサイズ、`3*`は`1*`の3倍のサイズという意味です。

## ◇4-3. Gridに配置

### ◎4-3-1. 左側（Rectangle）

ツールボックスから`Rectangle`をGridの左上のマスにドラッグ＆ドロップします。
プロパティウィンドウで`ブラシ` - `Fill`を選択します。
`単色ブラシ`タブを選択し、色を適当に選択します。
![vb311.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/e6140747-0a0f-1848-b99f-abe231f537b5.png)

配置した`Rectangle`を選択し、プロパティウィンドウの`レイアウト`を確認します。

|プロパティ |設定値|説明
|-----------|------|----
| Row       |0     |行位置。0始まりで上から。
| Column    |0     |列位置。0始まりで左から。
| RowSpan   |2     |行結合数。
| ColumnSpan|1     |列結合数。

![vb312.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/1de26fc5-1e34-1dd1-65a4-0f036cb9a09f.png)

`Rectangle`を右クリックし、`レイアウト` - `すべてリセット`を選択します。
![vb313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/10f73644-4737-b68e-4b25-5e8686754ecb.png)

位置・サイズ情報がクリアされて領域いっぱいに表示されました。
![vb314.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/dfee8fbc-452c-a8c5-45e2-035a15609bf8.png)

### ◎4-3-2. 上側（足し算）

`StackPanel`を上段2列目にドラッグ＆ドロップします。

![vb315.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/c22af5c9-e2e7-481e-47cc-2cc9dfff016e.png)

レイアウトを以下のように設定します。

|プロパティ |設定値|説明
|-----------|------|----
| Row       |0     |行位置。0始まりで上から。
| Column    |1     |列位置。0始まりで左から。
| RowSpan   |1     |行結合数。
| ColumnSpan|1     |列結合数。

配置したStackPanelを右クリックし、`レイアウト` - `すべてリセット`を選択します。
プロパティで`ブラシ` - `Background`を選択し、`単色ブラシ`タブを選択します。
RGBを以下のように設定します。

|プロパティ |設定値|
|-----------|------|
| R         |240   |
| G         |255   |
| B         |240   |

![vb316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/90e63de0-eeb6-e483-cb3c-177438b6fbc2.png)

緑の`StackPanel`の`Orientation`プロパティを横配置の`Horizontal`に変更します。
![vb317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/28fd5890-9a0a-e6bd-31c0-e40d8fddbde0.png)

`TextBoxk`, `TextBlock`, `TextBox`の順に配置します。
![vb318.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/e24d4eaa-19d1-5332-aec4-5e9325ebfd81.png)

2つの`TextBox`を一度にプロパティ設定します。
左側の`TextBox`を選択し、次に<kbd><kbd>Ctrl</kbd></kbd>キーを押しながら右側の`TextBox`を選択します。
そうするとプロパティの名前の部分が`2個のオブジェクトが選択されています`になります。
![vb319.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/df0c3d99-34b8-451f-a0c1-60154ed3d7c2.png)

以下のようにプロパティを設定します。

|プロパティ |設定値|説明
|-----------|------|----
| Width     |50    |幅
| Height    |30    |高さ
| Margin左  |10    |他のコントロールとの左余白
| Margin右  |10    |他のコントロールとの右余白
| Text      |空欄  |テキスト内容

![vb320.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/797a6596-d99d-cc83-3fe6-387dbcdeb3d6.png)

`TextBox`の間にある`TextBlock`を選択し、以下のようにプロパティを設定します。

|プロパティ       |設定値|説明
|-----------------|------|----
|VerticalAlignment|Center|縦位置
|FontSize         |18    |文字サイズ
|Text             |+     |テキスト内容

![vb321.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/cd9aad9e-a1f0-bbf5-9f9b-6ae510704925.png)

配置したコントロールが多くなってきたため、`ドキュメントアウトライン`を使うようにします。
メニューの`表示` - `その他のウィンドウ` - `ドキュメントアウトライン`を選択します。
![vb322.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/94228b07-40bf-80a6-94b4-bf3ea094d04f.png)

`Button`をドキュメントアウトラインの`StackPanel`上にドラッグ＆ドロップします。
![vb323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/60617cdf-03b3-2288-fa14-4a0cfa105c93.png)

![vb324.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/eeefce68-2789-05d0-2dcd-0e4ffc7d035b.png)

ボタンのプロパティを設定します。

|プロパティ       |設定値    |説明
|-----------------|----------|----
|名前             |CalcButton|コントロール名
|Width            |30        |幅
|VerticalAlignment|Center    |縦位置
|FontSize         |18        |文字サイズ
|Content          |=         |ボタンテキスト内容

![vb325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/2dea6ae1-a86e-0adf-3d84-8e977e87e699.png)

テキストボックスにも名前を付けます。
左側を`Num1Text`, 右側を`Num2Text`にします。
![vb326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/9f85f827-3b76-73f1-827e-59446eb092ae.png)

画面デザイナでボタンをダブルクリックします。
![vb327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/7b24b0b6-4282-7287-6596-0bff463d7c1c.png)

テキストボックスに入力された数値を足した結果をタイトルバーに表示する処理を書きます。

```vb:Window1.xaml.vb
Private Sub CalcButton_Click(sender As Object, e As RoutedEventArgs) Handles CalcButton.Click
    Dim num1 As Integer
    Dim num2 As Integer
    Dim total As Integer

    ' Num1Textに数値が入力されているか？
    If Integer.TryParse(Num1Text.Text, num1) Then
        ' Num2Textに数値が入力されているか？
        If Integer.TryParse(Num2Text.Text, num2) Then
            ' 計算してタイトルバーに表示
            total = num1 + num2
            Me.Title = $"{num1} 足す {num2} は {total} です。"
            Exit Sub
        End If
    End If

    Me.Title = "計算失敗"
End Sub
```

`Integer.TryParse`で1つ目の引数の文字列が数値に変換できるか確認します。
数値に変換できる場合、2つ目の引数に変換後の数値が設定され、戻り値がTrueで返ってきます。

先頭に`$`を付けた""で囲った文字列は、`{変数名}`で変数の中身を文字列中に埋め込むことができます。

## ◇4-4. 実行

実行してみます。
Window1を表示し、テキストボックスに数値を入力して`=`ボタンを押します。
タイトルバーに計算結果が表示されました。
![vb328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/059da0da-4c5f-fc4a-fb4f-7fc1780b7b83.png)

# ■STEP5. WrapPanelとファイル読み書き

## ◇5-1. 画面追加

新しい画面を追加します。
ソリューションエクスプローラーの`GuiTest1`プロジェクトを右クリック、`追加` - `ウィンドウ`を選択します。
名前に`Window2.xaml`が指定されているのでそのまま追加ボタンを押します。
![vb401.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/f29671af-0daf-e6e5-d7d8-8ddd51ac55fb.png)

## ◇5-2. 土台をGridからWrapPanelに変更

`Grid`を`WrapPanel`に変更します。
![vb402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/bc4a6a52-f837-0225-fe51-fdc60788524a.png)

## ◇5-3. コントロール配置

ドキュメントアウトラインの`WrapPanel`に`StackPanel`を2つドラッグ＆ドロップします。
![vb403.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/d32f9b7c-2104-5ec1-9879-539c33f086e1.png)

ドキュメントアウトラインで2つの`StackPanel`を選択状態（1つ目でクリック、2つ目で<kbd><kbd>Ctrl</kbd></kbd>を押しながらクリック）にします。
そして`Width`プロパティに`450`を設定します。
![vb404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/3fa60141-1ecf-b58b-20ab-c053b35255ad.png)

1つ目の`StackPanel`に`TextBox`, `Button`の順にドラッグ＆ドロップします。
2つ目の`StackPanel`に`Button`, `TextBox`の順にドラッグ＆ドロップします。
![vb405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/60988959-dbe9-7adc-2a1e-5d06eb713522.png)

## ◇5-4. プロパティ設定

一番上の`TextBox`のプロパティ設定をします。

|プロパティ       |設定値    |説明
|-----------------|----------|----
|名前             |InputText |コントロール名
|Height           |100       |高さ
|Margin左         |10        |他のコントロールとの左余白
|Margin右         |10        |他のコントロールとの右余白
|Margin上         |10        |他のコントロールとの上余白
|Margin下         |10        |他のコントロールとの下余白
|VerticalScrollBarVisibility|Visible        |縦スクロールバー
|AcceptsReturn    |True      |テキスト内で改行するか

![vb406.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/34695933-c1ea-a3ab-8e84-7ec026d80a9c.png)

その下の`Button`のプロパティ設定をします。

|プロパティ       |設定値    |説明
|-----------------|----------|----
|名前             |SaveButton |コントロール名
|Width           |150       |幅
|HorizontalAlignment|Left|横位置
|Margin左         |10        |他のコントロールとの左余白
|Margin下         |10        |他のコントロールとの下余白
|Content    |保存      |ボタンのテキスト

![vb407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/2b09770a-8ae9-3e57-98b0-804a8c2806d6.png)

下の`StackPanel`内の`Button`のプロパティ設定をします。

|プロパティ       |設定値    |説明
|-----------------|----------|----
|名前             |LoadButton |コントロール名
|Width           |150       |幅
|HorizontalAlignment|Left|横位置
|Margin左         |10        |他のコントロールとの左余白
|Margin上         |10        |他のコントロールとの上余白
|Content    |開く      |ボタンのテキスト

![vb408.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/524c702e-c615-32db-4807-5615e8dd15b7.png)

一番下の`TextBox`のプロパティ設定をします。

|プロパティ       |設定値    |説明
|-----------------|----------|----
|名前             |LoadText |コントロール名
|Height           |100       |高さ
|Margin左         |10        |他のコントロールとの左余白
|Margin右         |10        |他のコントロールとの右余白
|Margin上         |10        |他のコントロールとの上余白
|Margin下         |10        |他のコントロールとの下余白
|VerticalScrollBarVisibility|Visible        |縦スクロールバー
|IsReadOnly    |True      |読み取り専用

![vb409.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/79ca58ee-35cc-fd84-6700-be79236c16ba.png)

![vb410.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/3d2c55ea-ee53-f7e0-a1dc-7386a53798a4.png)

## ◇5-5. レイアウト確認用コントロール配置

`WrapPanel`の効果がわかりやすくなるよう、`WrapPanel`に`CheckBox`を4つ、ドラッグ＆ドロップします。
![vb411.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/2ba60e65-a9cc-a396-a38f-d5eb71681292.png)

## ◇5-6. ファイル保存処理作成

画面デザイナで保存ボタンをダブルクリックします。
![vb412.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/f23c2eb4-56f4-9594-0d52-62bd4adede30.png)

以下の処理を書きます。

```vb:Window2.xaml.vb
Private Sub SaveButton_Click(sender As Object, e As RoutedEventArgs) Handles SaveButton.Click
    ' 保存ダイアログの生成
    Dim dialog = New SaveFileDialog()

    ' 保存ダイアログの設定
    dialog.FileName = "GuiTest1ファイル.txt"
    dialog.Filter = "すべてのファイル|*.*|テキストファイル|*.txt"
    dialog.FilterIndex = 2

    ' 保存ダイアログ表示
    If dialog.ShowDialog() <> True Then
        ' キャンセル
        Exit Sub
    End If

    ' ファイル保存処理
    Using stream = dialog.OpenFile()
        Using writer = New StreamWriter(stream, Encoding.UTF8)
            Dim lineCnt As Integer = InputText.LineCount
            For i As Integer = 0 To lineCnt - 1
                ' 一行書き込み
                writer.Write(InputText.GetLineText(i))
            Next i
        End Using
    End Using
End Sub
```

## ◇5-7. 実行

動作確認をするため、Window2を表示するためのコードを書きます。
MainWindowに`Button`を追加、ダブルクリックし、以下のコードを書きます。

```vb:MainWindow.xaml.vb
Private Sub Button_Click_2(sender As Object, e As RoutedEventArgs)
    Dim window = New Window2()
    window.ShowDialog()
End Sub
```

実行してみます。
追加したボタンを押してWindow2を表示し、上のテキストボックスに何か入力します。
![vb413.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/ff0b54bc-4284-ffa7-08d6-ee100e0b708b.png)

保存ダイアログが表示されるので、保存先を指定して`保存`ボタンを押します。
![vb414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/07657d07-c669-4f39-8f88-533d5c9bc70d.png)

保存されたファイルを開いてみます。
![vb415.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/d0607207-2750-9ba4-4c30-0b5af0938513.png)

## ◇5-8. ファイル読み込み処理作成

画面デザイナで開くボタンをダブルクリックします。
![vb416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/6f3b0b75-b2a3-1117-1610-3d414e1ca284.png)

以下の処理を書きます。

```vb:Window2.xaml.vb
Private Sub LoadButton_Click(sender As Object, e As RoutedEventArgs) Handles LoadButton.Click
    '開くダイアログの生成
    Dim dialog = New OpenFileDialog()

    '開くダイアログの設定
    dialog.FileName = "GuiTest1ファイル.txt"
    dialog.Filter = "すべてのファイル|*.*|テキストファイル|*.txt"
    dialog.FilterIndex = 2

    ' 開くダイアログ表示
    If dialog.ShowDialog() <> True Then
        ' キャンセル
        Exit Sub
    End If

    ' ファイルを開く処理
    Using Stream = dialog.OpenFile()
        Using reader = New StreamReader(Stream, Encoding.UTF8)
            ' 一気に読み込み
            LoadText.Text = reader.ReadToEnd()
        End Using
    End Using
End Sub
```

## ◇5-9. 実行

実行してみます。
`開く`ボタンを押して、先ほど保存したファイルを開きます。
![vb417.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/f4074620-27db-dfa8-265a-afe664ace159.png)

読み込まれました。
![vb418.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/457c9573-9b3e-12d0-f25d-e1af6054fd48.png)

## ◇5-10. WrapPanel動作確認

最後にWrapPanelの効果を確認しやすくするため、上のStackPanelを選択し、`Background`プロパティで`グラデーションブラシ`タブを選択します。
![vb419.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/f6a77705-eb85-97c4-c4ce-56b2d5b128fa.png)

ウィンドウのサイズを変更しやすくするため、サイズ変更グリップを表示します。
画面デザイナ内のウィンドウのタイトルバーを選択して`Window`を選択状態にします。
`ResizeMode`プロパティを`CanResizeWithGrip`に設定します。
![vb420.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/6d592c5d-1135-b222-a578-bf2ffca19412.png)


実行してみます。
ウィンドウ幅を拡大したり縮小したりしてみます。
ウィドウサイズを変えるときは、右下のグリップをつかむとやりやすいです。
![vb422.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/90b15b0e-768b-6f7e-7804-2fee045b098f.png)

十分に幅を広げると`StackPanel`が横に並びます。
入りきらない分は下に回り込みます。
`StackPanel`で一つの塊なので、幅を広げても中のボタンが横に移動することはありません。
![vb421.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/48b19b68-c0f5-e5f2-eb42-016e8ca77529.png)