はじめての WPF【step: 1 .NET Core WPF 入門 2020】

当サイトの WPF 入門記事としては既に WPF Prism episode シリーズ がありますが、WPF Prism episode シリーズ を書いていた頃は右も左も分からず、試したことをとりあえず記事にしていたような状況だったので 1 つのネタで記事を書いた後に別の情報が見つかる事や、新しい方法を思い付く事も多く、本来 1 エントリに書くべき情報が複数の記事に分散する状況になった連載だと反省しています。

ですが現状では管理人もある程度 WPF や MVVM に慣れ、機能や流れも整理できてきたので新たに 2020 年版の WPF 入門として連載を開始する事にしました。

尚、この記事は Visual Studio 2019 Community Edition で .NET Core 3.1 以上 と C# を使用して、WPF アプリケーションを作成するのが目的のエントリなので、C# の文法や基本的なコーディング知識を持っている人を対象にしています。

WPF について

WPF は Windows Presentation Foundation の略称で、.NET Framework 3.0(2006/11/6 リリース)以降に含まれる Windows クライアントアプリの実行プラットフォームです。

発表当時はそれなりに騒がれていた記憶はありますが、あっと言う間に名前を聞かなくなり、技術的な情報もあまり増えないまま現在に至っている気がします。その後も Microsoft は UWP を発表しますが WPF 以上に鳴かず飛ばずの状態に思えるので、UWP は既に風前の灯火だと感じています。

WPF の学習コスト

.NET における Windows クライアントアプリの開発プラットフォームは Windows Form から始まり WPF → UWP と発表されて来ましたが結局、現時点でも最も使用されているのはおそらく Windows Form だろうと思われる皮肉な状況です。

日本国内では業務系システム開発に従事する人数はおそらく系統別では最多人数を誇ると思っていますが、技術力は低く技術に興味が薄い人が大半を占めると管理人は感じているので、今まで慣れている Windows Form を捨てて右も左も分からない WPF に移行するリスクを冒す選択はしないだろうと思っています。(あくまでも管理人個人の考えです)しかも WPF を選択したとしても得られるのが『コントロールの外観を自由に変更できてかっこいい感じの画面が作れるよ!』だけでは当然の結果のような気はします。

WPF(UWP 含む)が普及しない最大の原因はその学習コストの高さにあると管理人は考えていて、WPF を覚えようとして調べると『XAML』、『データバインディング』、『MVVM』、『Prism』、『Livet』、『ReactiveProperty』、『DI』、『ユニットテスト』… 等どこから手を付けていいかさえ分からない状況を前に途方に暮れると思います。管理人が実際にそうだったので WPF に手を出す事に躊躇っている人の気持ちはよく分かりますが、管理人自身も全く同じような状況(2018年当時)から覚え始めて今頃やっと何となくは理解できて来たような気がするので、管理人が今まで覚えてきたことを再整理して紹介する事を目的に新規連載をスタートすることにしました。

.NET Core で作る WPF アプリ

このサイトで連載している WPF Prism シリーズ は最初 .NET Framework を使った WPF アプリ開発入門として開始して途中から .NET Core ベースの記事に転換しましたが、この新連載では最初から .NET Core のみを対象にします。

.NET Core は 2019 年 9 月にリリースされたクロスプラットフォームが特徴の新しい .NET 実装で今後 Microsoft がリリースする開発プラットフォームのメインストリームになると発表されています。2020 年 11 月には .NET 5 として .NET Framework と統合予定(.NET Framework は 4.8 を最終バージョンとして残存予定)なので今から WPF を始めるなら .NET Core にも慣れておいた方が良いと思います。

2020 年 5 月現在は .NET 5 リリース前と言う事もあり、開発プラットフォームが混在していて状況がイマイチ掴めていないような場合は『【2020年版】.NET Framework / .Net Core / Xamarinの関係を整理~そして.NET 5へ – LIGHT11』等を読んでみてください。

.NET Core のみを対象にすると言っても現時点(2020 年 5 月現在)でソースコードに書く内容は .NET Framework で書いた場合とほとんど変わらないはずです。.NET Core で未サポートの機能もあるにはありますが、困る事はあまり多くないと思っています。加えて Nuget 等から取得するライブラリも警告は出ますが、.NET Framework 版でもそのまま利用できるのでとりあえず Visual Studio 2019(Ver. 16.3 以降)を入れて試してみる事をお勧めします。

.NET Core 版の Window Form はデザイナが未だ Preview 版(2020 年 5 月現在)だったりと完全サポートにはまだしばらくかかりそうなので WPF を覚えるのにも良いチャンスだと思います。.NET Core が WPF をサポートしたことで大手サイトでも WPF 入門記事の新規連載が開始されたところもあるので 1 度読んでみるのも良いと思います。

そしてこのエントリを書いている最中に開催された Microsoft のオンラインカンファレンス『Build Windows』で【Project REUNION】が発表され UWP と Win32(WPF/WinForm?)の UI 部品が WinUI 3.0 で統合されることになったようです!

黒歴史と言える Windows 8 から始まったデスクトップアプリ環境とモダンアプリ環境の分断政策が Project REUNION に至ることになった状況は『UWPからデスクトップアプリに回帰すべく、MSが送り出した「Project REUNION」- ASCII.jp』等で読むことができます。

今までは貧弱な UI コントロールの使用を強制されてきましたが、.NET 5 でようやく UWP と同一条件で開発できるようになり、Win32 アプリの復権も期待できそうです。一応、記事内に Windows Form の文字も見えるので『今後は XAML 一択!』とまでは言い切れないかもしれませんが、今から WPF を覚え始めても遅くない状況になりそうだと予想しています。(管理人の個人的な予想(希望?)です)

WPF の習得に欠かせない XAML

まず、WPF でアプリを作成する上で欠かせない最も基本的な知識の筆頭と言える【XAML】について簡単に紹介します。WPF を覚えようとして XAML を完全に理解してから次のステップに進もうと考える人も居ると思いますが、管理人の場合、初めて触れる概念が多過ぎて全く頭に入って来ないまま何度か挫折した経験があるので、『XAML についてはあまり深追いはせず追々覚える』ことにしてまず、動くアプリを作る事から始めてようやく XAML 自体も何となく理解できるようになった感じなので『XAML 訳分からん…』と思って挫折している人はとりあえず XAML の勉強からは離れて、まず動くモノを作る事を優先してみるのも手だと思います。

XAML は HTML のようなマークアップ記法が何となくでも理解できていればとりあえず書くことはできるはずですしビジュアルデザイナを使用すればタグを手打ちする必要もありません。管理人も『HTML みたいなモンだと思えば大丈夫やろ』的な感じでほとんど勉強せずとりあえず動くモノを作ることを優先して進みましたが、実際 XAML で困ったことはあまりなかったと思います。(記憶にあるのは Validation の ErrorTemplate くらいです)

とは言え予め知っておいた方が理解が早くなる情報もあるので管理人の経験から重要だと考える基本的な用語や使い方等をいくつか紹介します。

xmlns

src. 1 は Visual Studio 2019 で『WPF App(.NET Core)テンプレート』から生成される Window の XAML です。

管理人が XAML を 1 mm も知らなかった頃は、src. 1 の 2 ~ 6 行目の【xmlns(XML Name Space)】に多少戸惑ったので一応紹介しますが、これは C# のソースファイルで言えば using のようなものと考えて良いと思います。

5 行目の『xmlns:mc=』を例にすると『mc』を接頭辞(プレフィックス)と呼びます。プレフィックスには任意の名前を指定でき、= の右辺には名前空間を指定します。(using のエイリアスのようなもの)
xmlns に指定したプレフィックスを XAML 本文で使用する場合は、7 行目のように『mc:Ignorable』=『プレフィックス:クラス名(プロパティ)』のような形式で使用できます。xmlns は XML の仕様ですが XML も適当にしか勉強していない管理人は当時分かりませんでした。(まあ、その程度でも大して困らなかったとも言えます)

そして src. 1 の 2 ~ 5 行目は XAML の記述と画面作成に最低限必要な参照で、以下のような役割を持ちます。

xmlns内容
winfx/2006/xaml/presentationPresentationCore.dll を初めとして System.Windows 名前空間に含まれるクラスを参照するための既定の名前空間
この名前空間が規定に設定されているため、Window や Grid 等がプレフィックス無しで記述することができます。
又、コントロールのプロパティに使用されている列挙型等も含まれます
x: ~ winfx/2006/xamlXAML の言語機能を表すようです。
d: ~ expression/blend/2008Visual Studio の WPF デザインビューや Blend 等のビジュアルデザイナ上でのみ有効になるプロパティが定義されています。
d:DesignHeight や d:DesignWidth、d:DataContext 等はよく使うので覚えておいた方が良いと思います。
mc: ~ openxmlformats.org/markup-compatibility/2006テンプレートから生成すると自動的に含まれるので自分で書くことはほとんど無いと思いますが、Ignorable 属性を参照しています。
mc:Ignorable=”d” のように指定する事で『d: プレフィックス』が指すデザイン時設定を実行時に無効にします。

一応紹介しましたが、基本的に上に書いた事は覚えていなくても XAML を書く上で困ることはほとんどありません。せいぜい『d: プレフィックス』に書いた『d:DesignHeight』、『d:DesignWidth』、『d:DataContext』の 3 つを覚えておく程度で良いと思います。

新しいコントロールや自作した機能等(ビヘイビア等)を追加する場合等に xmlns(XML 名前空間)を手作業で追加する必要はありますが、Visual Studio 2019 では fig. 1 のように XAML 上でも IntelliSense が働くので入力に苦労する事はあまりないと思います。

fig.1 xmlns を追加する際の IntelliSense

そして、『xmlns』が指定されていない要素は開始タグで指定されたクラス(ここでは Window)のプロパティです。 src. 1 では Window の Title と Widht、Height プロパティを設定している事は分かると思います。後は実際に画面を作成して数をこなすことで覚えていけば良いと思います。

WPF のコンテンツモデル

XAML というより WPF の特性ですが、Windows Form の開発経験が長ければ長い程最初に戸惑うのが WPF のコンテンツモデルと言う考え方です。

パネル類を除く大半の WPF のコントロール(Window 含む)は【ContentControl】から継承されていて、ContentControl.Content プロパティには 1 つのオブジェクトしか設定することができません。例えば『Button コントロール』の Content プロパティに『文字列』と『アイコン等の画像』を同時に配置することはできません。これをコンテンツモデルと呼びます
WPF Prism episode: 3 の 第 2 章でも同じ内容を紹介しているので良ければ読んでください。

Button に複数のオブジェクト(『文字列』と『アイコン等の画像』)を配置したい場合は src. 2 のように Button 内にまずパネル(ここでは StackPanel)を配置して、その中に文字列とアイコン等の画像を配置することが必要です。

最初は戸惑うことも多いかもしれませんが、画面をいくつか作成すればその内慣れると思います。(管理人は慣れました)又、ここでは StackPanel を使用していますが、Grid でも DockPanel でも Panel 系であれば基本何を選択しても構いません

使用頻度の高い Panel 系コントロール

Panel 系コントロールは前項で紹介した StackPanel を始めとしていくつか用意されていますが、管理人の場合以下の 3 つだけでほとんど事足りています。

  • Grid
  • StackPanel
  • DockPanel

使用頻度の高い順に上から並べていますが、3 つとは言っても DockPanel は 1 ~ 2 回使った事がある程度なので実質 99 % は上 2 つの Panel でカバーできています。上で紹介した以外の Panel は『WPF のコンテナ(WPF)++C++; // 未確認飛行 C』等で確認してください。

Grid

Grid は配置した内部をテーブル状に分割してコントロールを配置でき、最大の特徴は各列・各行を割合(%)で指定することができる点で、Window のリサイズに合わせてコントロールもリサイズしたい場合にも便利な Panel です。
そして Grid は HTML の Table や WindowsForm の TableLayoutPanel と同じく fig. 2 の左下のようにセルを結合する事もできます。

fig. 2 Grid のセル結合

Grid のセル結合は HTML の Table や WindowsForm の TableLayoutPanel と違って、Grid 側に指定するのではなく src. 3 のようにセルに配置するコントロール側へ指定します。

src. 3 のように親のプロパティを『子側』で指定する仕組みを WPF では【添付プロパティ】と呼んでいて、セル結合だけでなく src. 3 にもあるように Grid 内の配置位置(Grid.Column、Grid.Row)を指定する場合も添付プロパティで指定していますが、今時点ではそのような仕組みがあると覚えておく程度で問題ありません。

管理人の個人的な考えですが、fig. 2 のようにセル結合を使ってレイアウトを作成しようと思うのは画面を単一の表としてしか捉えていないからだと思います。管理人が画面をレイアウトする場合、頭の中のイメージや概要設計(基本設計)書の画面イメージを元にコントロール群をセルに見立てて大きい塊ごとに分割し、各セル内に Grid を配置する【ネストした Grid】で作成しています。

fig. 2 をネストした Grid でレイアウトした場合は src. 4 のように 3 つの Grid を使用します。

src. 4 を実行した場合も fig. 2 と全く同じ画面が表示されます。
尚、fig. 2 は現在連載中の WPF UI Gallery シリーズで紹介しているサンプルを流用した画面です。

同じ画面が表示されるならセル結合を選択した方が簡単だと思うかもしれませんが、例えば『下段の結合しているグリーンのセルを画面サイズの 80% 幅にして画面中央に配置する』と言うような変更が必要になった場合、セル結合のまま修正するのは難しく、ネストした Grid に作成し直す必要がありますが、最初からネストした Grid で作成していれば src. 5 のように少しの変更で対応できます。

src. 5 は下段のレイアウト変更以外に上段と下段の間に 10px のマージンも追加していて、実行結果は fig. 3 のようになります。

fig.3 ネストした Grid で修正

このようにコントロール群を Grid のセルに見立てて Grid をネストして作成しておくと微調整や変更が必要になった場合の修正は少なくて済みます。XAML の場合 Windows Form とは異なり画面のレイアウト情報をテキストで記述するためコピペ等で簡単に修正できます。そのため『ネストした Grid』『セル結合』のどちらを選択しても修正は簡単だと言えますが、最初からネストした Grid で作成していれば作成中の微調整も簡単にできるので柔軟性に劣るセル結合をわざわざ選択する必要は無いと管理人は考えています。

StackPanel

Panel 内に配置したコントロールを水平方向又は垂直方向に並べたい場合に使用する Panel です。
XAML をいじり始めの頃は fig. 4 のような StackPanel のサンプルを見て『こんなパネルどこで使うねん…』と思っていました。

fig.4 StackPanel

<span class="su-quote-cite"><a href="https://qiita.com/YSRKEN/items/686068a359866f21f956#stackpanelwrappanel" target="_blank">WPFにおけるGUI構築講座 -座標ベタ書きから脱却しよう- - Qiita</a></span>

fig. 4 は StackPanel の使用例としてネットではよく見かけるサンプルなので、実際はどんな場合に使う Panel なのかピンと来ませんでしたが、管理人的に最も頻度が高いのは、fig. 5 の赤枠で囲んだ部分のように 2 ~ 3 個のコントロールを横に並べたい場合です。

fig.5 StackPanel 使用例

fig. 5 はほんの一例ですが、文章にすると以下のような場合です。

  • Windows の Explorer のような TreeView の TreeItem に画像と文字列等を並べて表示する場合
  • TextBlock と ToggleButton(TextBox)等のように入力コントロールとラベルを並べる場合
  • ダイアログ Windows の OK・キャンセルボタンを並べる場合

fig. 4 は垂直方向にコントロールを並べるのに StackPanel を使用していますが、管理人の場合は Grid を選択する事が多いと思います。StackPanel は隣り合ったコントロールをマージンゼロで配置するため、並べる全コントロールにマージンの設定が必要になる場合も多く面倒なので垂直方向にコントロールを並べたい場合は Grid を選択しています。

StackPanel は Grid と違って幅や高さを割合(%)で指定できませんが、単純に横方向や縦方向へ並べたいような場面では手軽に使える Panel なのでそれなりに使用頻度は高いと思います。

DockPanel

Panel 内部の上・下・左・右のいずれかに張り付くようにコントロールを配置できますが、Grid でもほとんど同じことができるので管理人はあまり使っていません。

 

Grid の項ではネストする Panel の例として Grid in Grid を紹介しましたが、Panel のネストは違う種類の Panel を入れ子にすることもできますし、『これが正解!』と言える法則もないので、自分が作りたいレイアウトを手早く簡単に作成するための方法を試行錯誤して見つけるしかないと思います。

XAML の編集についての余談

WPF の Window や UserControl にコントロールを追加するには、XAML のテキストを直接編集する方法と、ツールパレットからコントロールをポトペタして配置する方法がありますが、ポトペタでコントロールを配置すると余計なプロパティが設定される場合も多く、使い勝手はあまり良くないと思っています。

XAML のテキスト編集を強制するつもりは無いので、まずは使い易そうだと感じる方法から試してみれば良いと思います。XAML のテキストを直接編集すべき!的な意見を見かけたとしても、まずはビジュアルデザイナやプロパティウィンドウの GUI を先に使ってみて不便を感じてからテキストの直接編集へ移るのも全然アリだと思います。

管理人が Windows Form で 画面を作成していた時はコントロールをポトペタしながらレイアウトを考えることも多かったので、WPF でも同じようにビジュアルデザイナへポトペタしていましたが、テキストを直接修正した方が早いと感じる事や、逆に面倒くさいと感じる事とも多かったので今は XAML のテキストを直接編集する方が圧倒的に楽だと思っています。Grid の Column や Row 定義だけは未だにプロパティウィンドウを使用しますが、それ以外は XAML のテキストエディタへ直接タグを打ち込む事がほとんどです。

テキストの直接編集と言っても使用するコントロールや設定するプロパティはある程度決まってきますし、IntelliSense の入力補完のおかげで困ったことはほとんどありません。自分で使い易いと感じる方を選べば良いと思います。

WPF の今後

このエントリの初めの辺りで『WPF の普及は難しい』と書きましたが、2020 年の Microsoft オンラインカンファレンスで発表された『Project REUNION』に含まれる WinUI 3.0。そして 2021 年にリリース予定の .NET 6 に含まれる予定の GitHub で OSS として開発されている【.NET Multi-platform App UI(.NET MAUI)】 の発表で状況が変わる可能性が出て来たかもしれません。

MAUI については『[速報]マイクロソフト、新UIフレームワーク「.NET Multi-platform App UI」(.NET MAUI)発表。単一コードでマルチプラットフォーム対応。Microsoft Build 2020 – Publickey』や『Introducing .NET Multi-platform App UI – .NET Blog』等を見てください。

MAUI は Xamarin.Forms の進化形として開発されているようなのでやはり今後も XAML という技術が重要であるのは変わらなさそう(あくまでも管理人の主観です)なので .NET 5 や MAUI に備えて WPF を採用するプロジェクトが増えそうな気もしますが、Windows Form でも同じことが可能であればやはり普及は難しいとも考えられるので現状での予想は難しいと思っています。

Introducing .NET Multi-platform App UI – .NET Blog』等に書かれている Xamarin.Forms の進化形と言う文を見て『やっぱ XAML さいつよ』と思いましたが、どうも MAUI では XAML + MVVM だけでなく MVU(Model-View-Update)と言う管理人的には聞き慣れないパターンにも対応するようで nuitsjp さんが自身のブログ で紹介されています。

それでも XAML 技術自体が重要な技術であるのは変わらないとは思っているので、現時点では XAML プラットフォームの中では最もアプリが作成しやすい環境と言える WPF の重要性も高まりそうな予感が個人的にはしています。

コードビハインドで WPF アプリを実装する

XAML の概要と Panel の使い方が何となく分かれば、Window にコントロールを配置してそれぞれにコントロール名を付け、Window のコードビハインドにイベントハンドラを書いてアプリを作成する事もできます。現時点(2020 年 5 月現在)の WPF 開発では MVVM パターンを使った開発が主流だと思いますが、MVVM パターンもデータバインディングも利用せず Windows Form とほとんど同じ方式でアプリを作成することもできます。

コードビハインド + イベントハンドラを選択した場合でも、WPF MVVM L@bo #4 で紹介したような多階層アーキテクチャで設計すれば UI とアプリケーションロジックの分離もある程度はできますし、Windows Form 開発の経験があれば今までと変わらない方法で実装できるのでそこまで困ることは無いと思います。

ですが、Windows Form と同じ手法で開発すると言うことは Windows Form と同じ問題を内包する事と同意です。UI と疎結合にしたアプリケーションロジックをユニットテストするような MVVM パターンのメリットを受け取る事はできません

どちらが正しいと言う訳ではありませんが、WPF で開発する場合はどちらの手法で開発するかを決定する必要があり、コードビハインド + イベントハンドラを使用する方法を選択した場合は、この連載で紹介する内容はほとんど役に立たないと思うので他のサイトを見る方が良いと思います。

コードビハインド + イベントハンドラでアプリを作成する方法は管理人的に全く魅力を感じませんし、ブログのエントリとして公開する価値は管理人個人的には無いので、以降は WPF アプリを MVVM パターンで作成する方法を紹介する予定でしたが、これ以上は長くなり過ぎるので MVVM パターンについては次回に繰り越します。

と言う訳で、新たに WPF 入門をスタートしましたが、基本的に WPF Prism シリーズで紹介した内容から大きく変える予定は無いのでボチボチ進めていこうと思っています。

 

次回記事「MVVM フレームワーク充のススメ【step: 2 .NET Core WPF MVVM 入門 2020】」

 

 

おすすめ

2件のフィードバック

  1. comet より:

    最近になってWPF, .NET Core, Prismで開発を始めた私には本当に有難いです。
    これからも是非よろしくお願いいたします。

    そういえば、以下のURLから本ページへのリンクが貼られていないようでした。
    良ければ御確認お願いいたします。
    https://elf-mission.net/wpf-prism-index/

    • 沖田玲朗 より:

      読んで頂いてありがとうございます。
      WPF Prism episode シリーズに早めに追いつけるよう頑張ります。

      > そういえば、以下のURLから本ページへのリンクが貼られていないようでした。
      確認したら確かにいくつかリンクが抜けている箇所があったので修正しました。
      ありがとうございました。

comet へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください