はじめに
皆さんはラーメンは何で食べますか?
いえ、そうではなく、WPFとはいったい何でしょうか?
正式にはWindows Presentation Foundationといい、Windows Formに代わる新しいWindowsにおけるGUIアプリケーションのプラットフォームであり、登場は2006年。描画は内部でDirectXにより行われ、WinAPIのラッパーであるWindows Formとは根本から異なるシステムで……
などとそんなことが知りたいのならwikipediaでも読んでください。
もはや10年以上前に登場した技術であるにもかかわらず、本記事執筆時点(2018年)において、c#でGUIアプリとなった時に未だWindows Formに捕らわれているのをよく見かけます。
もちろん、既存の資産の運用、新しい技術の導入にかかるリスク、コストはあるのでしょう(私はプログラマとして食べているわけではないので詳しくは知らない)。
ですがWPFはいいぞと布教したいためにこの記事を書きます。(このweb時代にデスクトップアプリケーション自体オワコンでしょとか言わない)
WPFについて何となく知っているものの、抵抗を感じている人、未だWindows Formに捕らわれている人に読んでもらえたらと思います。
(そんな人がこの記事読むのかはさておき、一応WPF及びC#を全く知らない人の為に説明すると、WPFとは簡単に言うとWindowsで動くGUIソフトを作るための開発環境および基盤技術です。)
WPFとMVVM
WPFはMVVMデザインパターンで実装することが強く望まれます。これこそが、Windows Formとの大きな違いであり、Form捕らわれマンにとっての最初の壁です。
勿論、MVVMに則らずにformのように実装することも可能ですが、それはラーメンをフォークで食べるようなものです。邪道です。
MVVMデザインパターン
MVVMパターンとは何なのでしょうか?概略を理解していただくために、具体的なソースコードを出さずに概念的に説明したいと思います。
全体の構成は、View・ViewModel・Modelと呼ばれる要素から成ります。
ViewはTextBoxやButtonなどのUIに関する要素です。
Modelは各種データや計算処理などのロジック等を担当するオブジェクトです。
そして、ViewModelはViewModel自身あるいはModelが持つデータとViewをBindingによって繋ぐオブジェクトです。
このBindingという関係は、あるプロパティと別のプロパティの値を同期させるものだと思ってください。(片方が変更されると、もう片方もその値に変更される)
この時重要なことは、ViewとViewModelは図のように、Command及びBindingによってのみ繋がる関係であるということです。言い換えれば、両者は密結合であってはならないということです。
構図としては、ViewModelはViewに使われる側の立場なのですが、大原則として、ViewModelはViewが誰なのかを知ってはいけないのです。
(つまり、ViewModelがWindowやTextBoxなどのUI要素のインスタンスを保持して直接操作するなどは言語道断、フォークでラーメンを食べています。)
簡単な例を挙げましょう。
Windowに数値を入力するTextBoxを2つ置き、ボタンが押されたらその和を計算して表示するだけの足し算計算機を考えます。
この計算機をMVVMに則して実装した場合の動きを順に追っていきましょう。
- まず入力された2つの値はBindingによって、ViewModel (以下VM) に渡ります。
- 次に、計算ボタンが押されるとCommandによってViewからVMに「計算を実行しろ」という命令が出ます。
- 最後に、計算結果をVMのAnswerプロパティに格納すると、BindingされているViewの表示が自動で変更される。
というプロセスによって処理が実行されます。
おそらくここで、聡明な皆さんの120%の方が、「いやModelないじゃん」と思うことでしょう。その通りです。
この計算機の機能が薄っぺらすぎるためModelを作るまでもないのですが、Modelを使って正式な(?)MVVMにすると以下のようになります。
先ほどと変わった場所は、ModelとしてCalculatorというオブジェクトが追加され、VMはCalculator.AddValueというメソッドを呼ぶことで計算結果を得ています。
つまり、VMはModelを使って計算処理や何らかのロジックを呼ぶだけで、VM自身は具体的な処理はModelに任せているということです。
VMとModelの関係は、ViewとVMの関係ほど疎結合とはいかないものの、ModelはあくまでVMに使われる側の立場であることに変わりはなく、ModelはVMを知ってはいけません。