チュートリアル: .NET を使用して新しい WPF アプリを作成する
この短いチュートリアルでは、Visual Studio で新しい Windows Presentation Foundation (WPF) アプリを作成する方法について学習します。 最初のアプリが生成された後、コントロールを追加する方法と、イベントを処理する方法について説明します。 このチュートリアルを終了すると、リスト ボックスに名前を追加する簡単なアプリが作成されます。
このチュートリアルでは、次の作業を行う方法について説明します。
- 新しい WPF アプリを作成する
- フォームにコントロールを追加する
- コントロール イベントを処理してアプリの機能を提供する
- アプリを実行する
このチュートリアルに従ってビルドするアプリのプレビューを以下に示します。
前提条件
ヒント
Visual Studio 2022 バージョン 17.4 以降を使い、.NET 7 と .NET 6 の両方について個別のコンポーネントをインストールします。 .NET 7 のサポートは Visual Studio 2022 バージョン 17.4 で追加されました。
WPF アプリを作成する
新しいアプリを作成するための最初のステップは、Visual Studio を開き、テンプレートからアプリを生成することです。
Visual Studio を開きます。
[新しいプロジェクトの作成] を選択します。
[テンプレートの検索] ボックスに「wpf」と入力してから、Enter キーを押します。
[コード言語] ドロップダウンで、 [C#] または [Visual Basic] を選択します。
テンプレートの一覧で、 [WPF アプリケーション] を選んでから、 [次へ] を選択します。
重要
[WPF Application (.NET Framework)](WPF アプリケーション (.NET Framework)) テンプレートは選択しないでください。
次の図は、C# と Visual Basic の両方の .NET プロジェクト テンプレートを示しています。 コード言語フィルターを適用すると、対応するテンプレートが表示されます。
[新しいプロジェクトの構成] ウィンドウで、次の操作を行います。
- [プロジェクト名] ボックスに、「Names」と入力します。
- [ソリューションとプロジェクトを同じディレクトリに配置する] チェック ボックスをオンにします。
- 必要に応じて、別の [場所] を選んでコードを保存します。
- [次へ] ボタンを選択します。
[追加情報] ウィンドウで、[ターゲット フレームワーク] に [.NET 6.0 (長期的なサポート)] を選択します。 [作成] ボタンを選択します。
Visual Studio を開きます。
[新しいプロジェクトの作成] を選択します。
[テンプレートの検索] ボックスに「wpf」と入力してから、Enter キーを押します。
[コード言語] ドロップダウンで、 [C#] または [Visual Basic] を選択します。
テンプレートの一覧で、 [WPF アプリケーション] を選んでから、 [次へ] を選択します。
重要
[WPF Application (.NET Framework)](WPF アプリケーション (.NET Framework)) テンプレートは選択しないでください。
次の図は、C# と Visual Basic の両方の .NET プロジェクト テンプレートを示しています。 コード言語フィルターを適用すると、対応するテンプレートが表示されます。
[新しいプロジェクトの構成] ウィンドウで、次の操作を行います。
- [プロジェクト名] ボックスに、「Names」と入力します。
- [ソリューションとプロジェクトを同じディレクトリに配置する] チェック ボックスをオンにします。
- 必要に応じて、別の [場所] を選んでコードを保存します。
- [次へ] ボタンを選択します。
[追加情報] ウィンドウで、[ターゲット フレームワーク] に [.NET 7.0 (Standard Term Support)] (.NET 7.0 (標準期間のサポート)) を選びます。 [作成] ボタンを選択します。
アプリが生成されると、Visual Studio で既定のウィンドウ MainWindowの XAML デザイナー ペインが開くはずです。 デザイナーが表示されない場合は、 [ソリューション エクスプローラー] ペインで MainWindow.xaml ファイルをダブルクリックしてデザイナーを開きます。
Visual Studio の重要な部分
Visual Studio での WPF のサポートには、アプリを作成するときにやりとりする 5 つの重要なコンポーネントがあります。
ソリューション エクスプローラー
プロジェクトのファイル、コード、ウィンドウ、リソースのすべてがこのペインに表示されます。
Properties
このペインには、選択した項目に基づいて構成できるプロパティ設定が表示されます。 たとえば、 [ソリューション エクスプローラー] から項目を選択した場合、そのファイルに関連するプロパティ設定が表示されます。 [デザイナー] でオブジェクトを選択した場合は、その項目の設定が表示されます。
ツールボックス
ツールボックスには、フォームに追加できるすべてのコントロールが含まれています。 現在のフォームにコントロールを追加するには、コントロールをダブルクリックするか、コントロールをドラッグ アンド ドロップします。
XAML デザイナー
これは、XAML ドキュメント用のデザイナーです。 対話型であり、 [ツールボックス] からオブジェクトをドラッグ アンド ドロップすることができます。 デザイナーで項目を選択して移動することにより、アプリのユーザー インターフェイス (UI) を視覚的に作成できます。
デザイナーとエディターの両方が表示されている場合は、一方に対する変更がもう一方に反映されます。 デザイナーで項目を選択すると、 [プロパティ] ペインに、そのオブジェクトに関するプロパティと属性が表示されます。
XAML コード エディター
これは、XAML ドキュメント用の XAML コード エディターです。 XAML コード エディターは、デザイナーを使用せずに手動で UI を作成する手段です。 デザイナーにコントロールが追加されたときに、そのデザイナーによってコントロールのプロパティの値が推論される場合があります。 XAML コード エディターを使用すると、より多くの制御を行うことができます。
デザイナーとエディターの両方が表示されている場合は、一方に対する変更がもう一方に反映されます。 コード エディターでテキスト キャレットを移動すると、 [プロパティ] ペインに、そのオブジェクトに関するプロパティと属性が表示されます。
XAML を確認する
プロジェクトが作成された後、XAML コード エディターが表示されます。ここには、ウィンドウを表示するための最小限の XAML コードがあります。 エディターが開いていない場合は、 [ソリューション エクスプローラー] で MainWindow.xaml 項目をダブルクリックします。 次の例のような XAML が表示されるはずです。
<Window x:Class="Names.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:Names"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
わかりやすくするために、この XAML コードを分割してみましょう。 XAML は、WPF で使用されるコンパイラによって処理できるシンプルな XML です。 WPF UI を記述し、.NET コードとやりとりします。 XAML を理解するには、少なくとも XML の基本をよく理解しておく必要があります。
ドキュメントのルート <Window>
は、XAML ファイルによって記述されるオブジェクトの型を表します。 次の 8 つの属性が宣言されており、これらは一般的に 3 つのカテゴリに属しています。
名前空間
XML 名前空間で XML に構造体が提供され、ファイル内で宣言できる XML コンテンツが決まります。
メインの
xmlns
属性で、ファイル全体の XML 名前空間がインポートされます。この場合、WPF によって宣言される型にマップされます。 その他の XML 名前空間でプレフィックスが宣言され、XAML ファイル用のその他の型とオブジェクトがインポートされます。 たとえば、xmlns:local
名前空間の場合、local
プレフィックスが宣言され、プロジェクトによって宣言されたオブジェクト (Names
コード名前空間で宣言されたもの) にマップされます。x:Class
属性この属性で、
<Window>
がコードによって定義された型にマップされます。これは、Names.MainWindow
クラスである MainWindow.xaml.cs または MainWindow.xaml.vb ファイルです。Title
属性XAML オブジェクトで宣言される通常の属性により、そのオブジェクトのプロパティが設定されます。 この例では、
Title
属性によってWindow.Title
プロパティが設定されます。
ウィンドウを変更する
まず、プロジェクトを実行して、既定の出力を確認します。 ポップアップ表示されるウィンドウには、コントロールはなく、MainWindow というタイトルが示されます。
例のアプリの場合、このウィンドウは大きすぎて、タイトル バーがわかりにくくなっています。 XAML の適切な属性を次の値に変更して、ウィンドウのタイトルとサイズを変更します。
<Window x:Class="Names.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:Names"
mc:Ignorable="d"
Title="Names" Height="180" Width="260">
<Grid>
</Grid>
</Window>
レイアウトを準備する
WPF には、さまざまなレイアウト コントロールを持つ強力なレイアウト システムが用意されています。 レイアウト コントロールは、子コントロールを配置したりサイズを設定したりするのに役立ち、自動的に実行することもできます。 この XAML に用意されている既定のレイアウト コントロールは、<Grid>
コントロールです。
Grid
コントロールを使用すると、テーブルと同じように行と列を定義し、特定の行と列の組み合わせの境界内にコントロールを配置できます。 Grid
には、任意の数の子コントロールまたはその他のレイアウト コントロールを追加できます。 たとえば、特定の行と列の組み合わせに別の Grid
コントロールを配置できます。その後、新しい Grid
でより多くの行と列を定義し、独自の子を持つことができます。
<Grid>
コントロールにより、コントロールが配置される行と列が定義されます。 グリッドには常に単一の行と列が宣言されています。つまり、グリッドは既定で単一のセルになります。 その場合、実際にはそれほど柔軟にコントロールを配置できません。
新しい行と列を追加する前に、<Grid>
要素に新しい属性 (Margin="10"
) を追加します。 これでウィンドウからグリッドがインセットされ、少し見栄えが良くなります。
次に、2 つの行と 2 つの列を定義し、グリッドを 4 つのセルに分割します。
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
XAML コード エディターまたは XAML デザイナーでグリッドを選択すると、XAML デザイナーに各行と列が表示されることがわかります。
最初のコントロールを追加する
これでグリッドが作成されたので、コントロールの追加を開始できます。 まず、ラベル コントロールから始めます。 <Grid>
要素内で、行と列の定義の後に新しい <Label>
要素を作成し、Names
の文字列値を指定します。
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Names</Label>
</Grid>
<Label>Names</Label>
でコンテンツ Names
が定義されます。 コントロールによっては、コンテンツの処理方法が理解されるものとされないものがあります。 コントロールのコンテンツは、Content
プロパティにマップされます。 コンテンツを XAML 属性構文で設定する場合は、この <Label Content="Names" />
形式を使用します。 どちらの方法でも、テキスト Names
を表示するようにラベルのコンテンツを設定することで同じことが行われます。
しかし、問題があります。グリッドの最初の行と列に自動的に割り当てられたラベルが、ウィンドウの半分を占めています。 最初の行では、その行をラベルに使用するだけなので、それほど多くのスペースは必要ありません。 最初の <RowDefinition>
の Height
属性を *
から Auto
に変更します。 Auto
値を指定すると、グリッド行のサイズがそのコンテンツ (この場合はラベル コントロール) のサイズに自動的に設定されます。
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
デザイナーに、使用可能な高さを占める量が少なくなったラベルが表示されるようになったことに注目してださい。 これで、次の行の占有スペースが増えました。 ほとんどのコントロールで、見栄えを最高のものにするために占有する必要がある何らかの高さと幅の値が定義されます。 たとえば、ラベル コントロールには、確実に読み取れるようにする高さの値があります。
コントロールの配置
それでは、コントロールの配置について説明します。 上のセクションで作成されたラベルは、グリッドの行 0 と列 0 に自動的に配置されました。 行と列の番号付けは 0 から始まり、新しい行または列ごとに 1 ずつ増加します。 コントロールにグリッドに関する知識はないため、コントロールでグリッド内の配置を制御するプロパティは定義されません。 コントロールは、コントロールを配置する方法を定義する独自の規則セットを持つ他のレイアウト コントロール内に配置されている場合もあります。
コントロールにグリッドに関する知識がない場合に、別の行または列を使用するようにコントロールに指示するにはどうすればよいでしょうか? 添付プロパティがあります。 グリッドでは、WPF によって提供される強力なプロパティ システムを利用します。 そのグリッドにより、子コントロールで宣言および使用できる新しいプロパティが定義されます。 これらのプロパティは実際にはコントロール自体には存在せず、コントロールがグリッドに追加されたときにそのグリッドによって添付されます。
グリッドにより、子コントロールの行と列の配置を決定する 2 つのプロパティ (Grid.Row
と Grid.Column
) が定義されます。 これらのプロパティがコントロールから省略されている場合、既定値の 0 が設定されていることが示されるため、コントロールはグリッドの行 0
と列 0
に配置されます。 Grid.Column
属性を 1
に設定し、<Label>
コントロールの配置を変更してみてください。
<Label Grid.Column="1">Names</Label>
これでラベルが 2 番目の列にどのように移動されたかに注目してください。 Grid.Row
および Grid.Column
添付プロパティを使用して、次に作成するコントロールを配置できます。 しかしここでは、ラベルを列 0 に復元します。
名前リスト ボックスを作成する
これでグリッドのサイズが正しく設定され、ラベルが作成されたので、そのラベルの下の行にリスト ボックス コントロールを追加します。 リスト ボックスは、行 1
と列 0
に配置されます。 また、このコントロールに lstNames
という名前を付けます。 コントロールに名前を付けたら、分離コードで参照できます。 名前は、x:Name
属性を使用してコントロールに割り当てられます。
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Names</Label>
<ListBox Grid.Row="1" x:Name="lstNames" />
</Grid>
残りのコントロールを追加する
追加する最後の 2 つのコントロールは、テキスト ボックスとボタンです。ユーザーはこれらを使用して、リスト ボックスに追加する名前を入力します。 しかし、グリッド用にさらに多くの行と列を作成してみるのではなく、これらのコントロールを <StackPanel>
レイアウト コントロールに配置します。
スタック パネルとグリッドでは、コントロールの配置方法が異なります。 グリッドには Grid.Row
および Grid.Column
添付プロパティを使用してコントロールを配置する場所を指示しますが、スタック パネルは、最初のコントロールを配置し、その後に次のコントロールを配置して、すべてのコントロールが配置されるまで続行することで自動的に動作します。 各コントロールは他のものの下に "スタック" されます。
リスト ボックスの後に <StackPanel>
コントロールを作成し、グリッド行 1
列 1
に配置します。 値が 5,0,0,0
の Margin
という名前の別の属性を追加します。
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Names</Label>
<ListBox Grid.Row="1" x:Name="lstNames" />
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
</StackPanel>
その Margin
属性はグリッドで以前に使用されたものですが、入力したのは単一の値 10
のみです。 ここでは、スタック パネルで 5,0,0,0
という値を使用しました。 余白は Thickness
型で、両方の値を解釈できます。 太さでは、四角形のフレームの各辺の左、上、右、下の周囲のスペースがそれぞれ定義されます。 余白の値が単一の値の場合は、4 辺すべてにその値が使用されます。
次に、<StackPanel>
に <TextBox>
および <Button>
コントロールを作成します。
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
<TextBox x:Name="txtName" />
<Button x:Name="btnAdd" Margin="0,5,0,0">Add Name</Button>
</StackPanel>
ウィンドウのレイアウトが完了しました。 しかし、アプリには実際に機能するロジックがありません。 次は、コントロール イベントをコードにフックし、アプリに実際に何かを実行させる必要があります。
Click イベントのコードを追加する
作成した <Button>
には、ユーザーがボタンを押したときに発生する Click
イベントがあります。 このイベントをサブスクライブし、リスト ボックスに名前を追加するコードを追加することができます。 XAML 属性を追加することによってコントロールのプロパティを設定するのと同じように、XAML 属性を使用してイベントをサブスクライブできます。 Click
属性を ButtonAddName_Click
に設定します
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
<TextBox x:Name="txtName" />
<Button x:Name="btnAdd" Margin="0,5,0,0" Click="ButtonAddName_Click">Add Name</Button>
</StackPanel>
ここで、ハンドラー コードを生成する必要があります。 ButtonAddName_Click
を右クリックし、 [定義へ移動] を選択します。 このアクションにより、入力したハンドラー名と一致するメソッドが分離コードで自動的に生成されます。
private void ButtonAddName_Click(object sender, RoutedEventArgs e)
{
}
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)
End Sub
次は、これらの 3 つの手順を行うために以下のコードを追加します。
- テキスト ボックスに名前が含まれていることを確認します。
- テキスト ボックスに入力された名前がまだ存在しないことを確認します。
- リスト ボックスに名前を追加します。
private void ButtonAddName_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(txtName.Text) && !lstNames.Items.Contains(txtName.Text))
{
lstNames.Items.Add(txtName.Text);
txtName.Clear();
}
}
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)
If Not String.IsNullOrWhiteSpace(txtName.Text) And Not lstNames.Items.Contains(txtName.Text) Then
lstNames.Items.Add(txtName.Text)
txtName.Clear()
End If
End Sub
アプリを実行する
イベントをコーディングしたので、F5 キーを押すか、メニューから [デバッグ]>[デバッグの開始] を選択して、アプリを実行できます。 ウィンドウが表示され、テキスト ボックスに名前を入力し、ボタンをクリックすることでそれを追加できます。
次のステップ
.NET Desktop feedback