■はじめに
Visual Basic .NET(VB.NET)と.NET 5でGUIアプリを作ってみます。
■環境
- Windows 10
- Visual Studio 2019 Community Version 16.9.0
- .NET 5.0
■準備
Visual Studio 2019のコミュニティ版をダウンロードしてインストールします。
Visual Studio 2019 for Windowsのダウンロード
インストールが終わったらVisual Studio Installerを起動し、ワークロードタブの.NET デスクトップ開発にチェックが入っていることを確認します。チェックが入っていなかったらチェックを入れてインストールします。

※Visual Studio 2019を既にインストール済みの場合は、バージョンが16.9以上であることを確認してください。
古いバージョンの場合は更新してください。
■STEP1. 画面を表示する
◇1-1. プロジェクトの作成
Visual Studio 2019を起動します。
新しいプロジェクトの作成ボタンを押します。

右上のドロップダウンリストからVisual Basicを、上の検索ボックスにwpfを入力し、
WPFアプリケーションを選択して次へボタンを押します。
※間違えてWPFアプリ(.NET Framework)を選ばないように。

プロジェクト名を付けます。ここではGuiTest1にしました。
次へボタンを押します。

ターゲットフレームワークに.NET 5.0を選択します。
作成ボタンを押します。

各エリアの名称と役割は以下の通りです。
- (1)ツールボックス
- 配置できるコントロールが一覧表示されています。
- (2)デザイナー デザインエリア(以後「画面デザイナ」と表記)
- 画面イメージです。
- (3)デザイナー XAMLエリア(以後「Xamlエディター」と表記)
- 画面定義です。
- (4)ソリューションエクスプローラー
- プログラムのファイル構成が表示されます。
そしてこれがコントロールの設定値(プロパティ)を編集するためのプロパティウィンドウです。
これらが表示されていない場合、表示メニューから表示させてください。

◇1-2. Visual Studioから実行
まずはいきなり実行してみます。
ツールバーの緑の三角の実行ボタンを押してください。
EXEファイルが作成され、プログラムが起動します。

まっさらな画面が表示されました。
×ボタンで終了してください。

◇1-3. 直接EXEを実行
さきほど実行したときにEXEが作られたので今度はエクスプローラーから直接実行してみます。
ソリューションエクスプローラーでプロジェクトGuiTest1を右クリックし、エクスプローラーでフォルダを開くを選択してください。

エクスプローラーが起動するので bin → Debug → net5.x-windowsとフォルダを開いていってください。

GuiTest1.exeをダブルクリックしてください。
先ほどと同じ画面が表示されました。
×ボタンで閉じてください。

■STEP2. StackPanelとボタン
次はボタンをいくつか配置してみます。
◇2-1. 土台をGridからStackPanelに変更
コントロールを配置する前に、土台となる部分をGridからStackPanelに変更します。
画面デザイナ中のウィンドウの白い部分(Grid)で右クリックし、レイアウトの種類の変更 - StackPanelを選択します。

画面デザイナ上では見た目の変化はありませんが、XamlエディターのGridタグがStackPanelタグに変わりました。
ツールボックスからButtonをStackPanelにドラッグ&ドロップします。

◇2-2. ボタン配置
Buttonが追加されました。
位置やサイズを指定しなくても自動的に上端に配置されます。
引き続き、追加で2つボタンをドラッグ&ドロップします。

積み重なるようにButtonが配置されました。
これがStackPanelの機能です。

◇2-3. ボタンのプロパティ変更
真ん中のButtonを選択し、プロパティウィンドウで共通 - Contentプロパティにぼたんと入力してEnterしてください。
画面デザイナのボタンテキストとXamlエディターに反映されます。

一番下のButtonを選択し、プロパティウィンドウでブラシ - Backgroundプロパティを選択し、右端のブラシリソースタブを選択、InfoBrushKeyを選択します。
これでボタン背景色が変わります。

◇2-4. ボタンクリック処理の作成
自動的にコードエディタに移動します。
MainWindow.xamlのタブがデザイナー、MainWindow.xaml.vbのタブがコードです。

メッセージボックスを表示するコードを書きます。
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
MessageBox.Show("こんにちは")
End Sub
◇2-5. 実行
メッセージボックスと画面を閉じてください。
◇2-6. 共通ボタン処理
次は別の方法でボタンクリック時の処理を作ります。
画面デザイナで真ん中のボタンを選択し、プロパティウィンドウの稲妻マークを選択してください。
ボタンに設定できるイベントの一覧が出てきます。
(プロパティの一覧に戻るには、稲妻マークの左にある工具のマークをクリックしてください)

Clickイベントにボタンクリック共通処理と入力してEnterしてください。

コードを以下のように書いてください。
'から始まる行はコメントです。
Private Sub ボタンクリック共通処理(sender As Object, e As RoutedEventArgs)
' 押されたボタンのテキストをタイトルバーに表示
Me.Title = CType(sender, Button).Content & "が押されました。"
End Sub
引数のsenderには押したボタンが渡されるので、そのボタンのテキスト(Content)をウィンドウのタイトルバーに表示します。
MainWindow.xamlのタブを選択してデザイナーに戻り、
真ん中のボタンに設定したClickイベントの ボタンクリック共通処理の文字列をコピーし、
一番下のボタンを選択し、Clickイベントに貼り付けてEnterしてください。

ここまででXamlのStackPanel配下は以下のようになっているはずです。
(見やすいように改行を入れています。自動的にXamlを整形する拡張機能もあります[参考])
<StackPanel>
<Button
Content="Button"
Click="Button_Click"/>
<Button
Content="ぼたん"
Click="ボタンクリック共通処理"/>
<Button
Content="Button"
Background="{DynamicResource {x:Static SystemColors.InfoBrushKey}}"
Click="ボタンクリック共通処理"/>
</StackPanel>
◇2-7. 実行
実行してみます。
画面が表示されたら真ん中のボタンを押します。

1つのボタンクリック処理を2つのボタンで利用しました。
■STEP3. 別画面表示
別の画面を表示する処理を作ってみます。
◇3-1. 画面追加
ソリューションエクスプローラーのGuiTest1プロジェクトを右クリック、追加 - ウィンドウを選択します。

名前にWindow1.xamlが指定されているのでそのまま追加ボタンを押します。

◇3-2. 画面表示処理作成
MainWindow.xamlタブを選択します。
Buttonを新たに追加し、Contentプロパティに画面表示を設定します。

稲妻マークを選択し、Clickのテキストボックス内をダブルクリックします。

コードエディタに移動するので先ほど追加したWindow1を生成して表示する処理を書きます。
Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
Dim window = New Window1()
window.ShowDialog()
End Sub
◇3-3. 実行
実行してみます。
画面表示ボタンを押すとWindow1が表示されました。

■STEP4. Gridと計算
次はGridを使ってみます。
◇4-1. Grid分割
画面デザイナでGridを選択した状態で下図の赤く塗ったあたりにマウスカーソルを持っていくと+マークが付きます。

◇4-2. 分割サイズ変更
分割の割合を調整します。
(1)で囲ったあたりにマウスカーソルをポイントします。
(2)の数字部分に1*を入力します。

1列目が見えなくなりましたが、気にせず2列目に2*を入力します。

2*は1*の2倍のサイズ、3*は1*の3倍のサイズという意味です。
◇4-3. Gridに配置
◎4-3-1. 左側(Rectangle)
ツールボックスからRectangleをGridの左上のマスにドラッグ&ドロップします。
プロパティウィンドウでブラシ - Fillを選択します。
単色ブラシタブを選択し、色を適当に選択します。

配置したRectangleを選択し、プロパティウィンドウのレイアウトを確認します。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| Row | 0 | 行位置。0始まりで上から。 |
| Column | 0 | 列位置。0始まりで左から。 |
| RowSpan | 2 | 行結合数。 |
| ColumnSpan | 1 | 列結合数。 |
Rectangleを右クリックし、レイアウト - すべてリセットを選択します。

位置・サイズ情報がクリアされて領域いっぱいに表示されました。

◎4-3-2. 上側(足し算)
StackPanelを上段2列目にドラッグ&ドロップします。
レイアウトを以下のように設定します。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| Row | 0 | 行位置。0始まりで上から。 |
| Column | 1 | 列位置。0始まりで左から。 |
| RowSpan | 1 | 行結合数。 |
| ColumnSpan | 1 | 列結合数。 |
配置したStackPanelを右クリックし、レイアウト - すべてリセットを選択します。
プロパティでブラシ - Backgroundを選択し、単色ブラシタブを選択します。
RGBを以下のように設定します。
| プロパティ | 設定値 |
|---|---|
| R | 240 |
| G | 255 |
| B | 240 |
緑のStackPanelのOrientationプロパティを横配置のHorizontalに変更します。

TextBoxk, TextBlock, TextBoxの順に配置します。

2つのTextBoxを一度にプロパティ設定します。
左側のTextBoxを選択し、次にCtrlキーを押しながら右側のTextBoxを選択します。
そうするとプロパティの名前の部分が2個のオブジェクトが選択されていますになります。

以下のようにプロパティを設定します。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| Width | 50 | 幅 |
| Height | 30 | 高さ |
| Margin左 | 10 | 他のコントロールとの左余白 |
| Margin右 | 10 | 他のコントロールとの右余白 |
| Text | 空欄 | テキスト内容 |
TextBoxの間にあるTextBlockを選択し、以下のようにプロパティを設定します。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| VerticalAlignment | Center | 縦位置 |
| FontSize | 18 | 文字サイズ |
| Text | + | テキスト内容 |
配置したコントロールが多くなってきたため、ドキュメントアウトラインを使うようにします。
メニューの表示 - その他のウィンドウ - ドキュメントアウトラインを選択します。

ButtonをドキュメントアウトラインのStackPanel上にドラッグ&ドロップします。

ボタンのプロパティを設定します。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| 名前 | CalcButton | コントロール名 |
| Width | 30 | 幅 |
| VerticalAlignment | Center | 縦位置 |
| FontSize | 18 | 文字サイズ |
| Content | = | ボタンテキスト内容 |
テキストボックスにも名前を付けます。
左側をNum1Text, 右側をNum2Textにします。

テキストボックスに入力された数値を足した結果をタイトルバーに表示する処理を書きます。
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を表示し、テキストボックスに数値を入力して=ボタンを押します。
タイトルバーに計算結果が表示されました。

■STEP5. WrapPanelとファイル読み書き
◇5-1. 画面追加
新しい画面を追加します。
ソリューションエクスプローラーのGuiTest1プロジェクトを右クリック、追加 - ウィンドウを選択します。
名前にWindow2.xamlが指定されているのでそのまま追加ボタンを押します。

◇5-2. 土台をGridからWrapPanelに変更
◇5-3. コントロール配置
ドキュメントアウトラインのWrapPanelにStackPanelを2つドラッグ&ドロップします。

ドキュメントアウトラインで2つのStackPanelを選択状態(1つ目でクリック、2つ目でCtrlを押しながらクリック)にします。
そしてWidthプロパティに450を設定します。

1つ目のStackPanelにTextBox, Buttonの順にドラッグ&ドロップします。
2つ目のStackPanelにButton, TextBoxの順にドラッグ&ドロップします。

◇5-4. プロパティ設定
一番上のTextBoxのプロパティ設定をします。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| 名前 | InputText | コントロール名 |
| Height | 100 | 高さ |
| Margin左 | 10 | 他のコントロールとの左余白 |
| Margin右 | 10 | 他のコントロールとの右余白 |
| Margin上 | 10 | 他のコントロールとの上余白 |
| Margin下 | 10 | 他のコントロールとの下余白 |
| VerticalScrollBarVisibility | Visible | 縦スクロールバー |
| AcceptsReturn | True | テキスト内で改行するか |
その下のButtonのプロパティ設定をします。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| 名前 | SaveButton | コントロール名 |
| Width | 150 | 幅 |
| HorizontalAlignment | Left | 横位置 |
| Margin左 | 10 | 他のコントロールとの左余白 |
| Margin下 | 10 | 他のコントロールとの下余白 |
| Content | 保存 | ボタンのテキスト |
下のStackPanel内のButtonのプロパティ設定をします。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| 名前 | LoadButton | コントロール名 |
| Width | 150 | 幅 |
| HorizontalAlignment | Left | 横位置 |
| Margin左 | 10 | 他のコントロールとの左余白 |
| Margin上 | 10 | 他のコントロールとの上余白 |
| Content | 開く | ボタンのテキスト |
一番下のTextBoxのプロパティ設定をします。
| プロパティ | 設定値 | 説明 |
|---|---|---|
| 名前 | LoadText | コントロール名 |
| Height | 100 | 高さ |
| Margin左 | 10 | 他のコントロールとの左余白 |
| Margin右 | 10 | 他のコントロールとの右余白 |
| Margin上 | 10 | 他のコントロールとの上余白 |
| Margin下 | 10 | 他のコントロールとの下余白 |
| VerticalScrollBarVisibility | Visible | 縦スクロールバー |
| IsReadOnly | True | 読み取り専用 |
◇5-5. レイアウト確認用コントロール配置
WrapPanelの効果がわかりやすくなるよう、WrapPanelにCheckBoxを4つ、ドラッグ&ドロップします。

◇5-6. ファイル保存処理作成
以下の処理を書きます。
Imports System.IO
Imports System.Text
Imports Microsoft.Win32
Public Class Window2
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
End Class
◇5-7. 実行
動作確認をするため、Window2を表示するためのコードを書きます。
MainWindowにButtonを追加、ダブルクリックし、以下のコードを書きます。
Private Sub Button_Click_2(sender As Object, e As RoutedEventArgs)
Dim window = New Window2()
window.ShowDialog()
End Sub
実行してみます。
追加したボタンを押してWindow2を表示し、上のテキストボックスに何か入力します。

保存ダイアログが表示されるので、保存先を指定して保存ボタンを押します。

◇5-8. ファイル読み込み処理作成
以下の処理を書きます。
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. 実行
実行してみます。
開くボタンを押して、先ほど保存したファイルを開きます。

◇5-10. WrapPanel動作確認
最後にWrapPanelの効果を確認しやすくするため、上のStackPanelを選択し、Backgroundプロパティでグラデーションブラシタブを選択します。

ウィンドウのサイズを変更しやすくするため、サイズ変更グリップを表示します。
画面デザイナ内のウィンドウのタイトルバーを選択してWindowを選択状態にします。
ResizeModeプロパティをCanResizeWithGripに設定します。

実行してみます。
ウィンドウ幅を拡大したり縮小したりしてみます。
ウィドウサイズを変えるときは、右下のグリップをつかむとやりやすいです。

十分に幅を広げるとStackPanelが横に並びます。
入りきらない分は下に回り込みます。
StackPanelで一つの塊なので、幅を広げても中のボタンが横に移動することはありません。

■STEP6. デザイン変更
◇6-1. プロジェクト作成
GuiTest1は終了し、新しくプロジェクトを作成します。
プロジェクト名はGuiTest2、フレームワークは.NET 5.0にします。
ソリューションエクスプローラーでGuiTest2プロジェクトを右クリックし、「NuGetパッケージの管理」を選択します。

「参照」タブを選択し、検索ボックスにmodernwpfuiと入力、「ModernWpfUI」をインストールします。

◇6-2. Applicationの設定
Application.xamlにxmlns:ui="http://schemas.modernwpf.com/2019"を追加し、
<Application.Resources>の中にResourceDictionaryを追加します。
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GuiTest2"
xmlns:ui="http://schemas.modernwpf.com/2019"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemeResources />
<ui:XamlControlsResources />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>
◇6-3. MainWindowの設定
MainWindow.xamlに
xmlns:ui="http://schemas.modernwpf.com/2019"と
ui:WindowHelper.UseModernWindowStyle="True"を追加します。
<Window x:Class="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:GuiTest2"
xmlns:ui="http://schemas.modernwpf.com/2019"
ui:WindowHelper.UseModernWindowStyle="True"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
◇6-4. プロジェクトの設定
ソリューションエクスプローラーでGuiTest2プロジェクトをダブルクリックします。
TargetFrameworkをnet5.0-windows10.0.18362.0に編集します。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<RootNamespace>GuiTest2</RootNamespace>
<UseWPF>true</UseWPF>
</PropertyGroup>
:
:
◇6-5. ビルド
ここまでで一度ビルドしてみます。
メニューのビルド - ソリューションのリビルドを選択します。
◇6-6. コントロール配置
XamlエディターでGridをui:SimpleStackPanelに書き換えます。
そしてSpacing="10"を追加します。
:
:
<ui:SimpleStackPanel Spacing="10">
</ui:SimpleStackPanel>
</Window>
SimpleStackPanelにコントロールを追加していきます。
ツールバーの「コモンWPFコントロール」から
Buttonを2つ、ChekBoxを2つ、RadioButtonを2つ、TextBoxを1つ、
「すべてのWPFコントロール」からSliderを1つ、画面にドラッグ&ドロップします。



































