The following two tabs change content below.
アバター画像

メンバー

福岡市博多区でWebシステム開発の受託・ラボ型SES・web集客サービス、3つのWebサービスを提供中

WPFを触り始めたとき、

「MVVMって何?」
「なんでこんなに複雑なの?」

と感じたことはないでしょうか。

私自身も最初は、「コードビハインドで書けばよくない?」と思っていました。

ボタンのクリックイベントを書いて、その中で処理して、画面更新する。

これで動くのに、なぜわざわざViewModelを用意するのか。。。
正直、最初は遠回りにしか見えませんでした。

ただ、実務で少しずつ規模の大きい画面を触るようになってから、「これは設計の問題なんだ」と考え方が変わりました。

この記事では、MVCとの違いをベースにしながら、
MVVMの考え方とWPFとの関係を、もう一歩踏み込んで整理していきます。

MVCとは何か ―『手動でつなぐ設計』の正体

MVCは、アプリケーションを以下の3つに分ける設計パターンです。

・Model:データ
・View:画面
・Controller:入力、制御

一見シンプルですが、重要なのはControllerがすべてを仲介するという点を覚えてもらえれば大丈夫です。

MVCの流れ

実際にどのような流れでクライアント⇒サーバー⇒クライアントの処理を辿っているのか説明します。

ユーザー操作

Controller

Modelを更新

View更新(手動)

処理フローのイメージは以下の通りです。

public void OnButtonClick()
{
// ユーザー入力を取得
var inputName = view.GetInputName();

// Model更新
model.Name = inputName;

// View更新(手動)
view.SetName(model.Name);
}

上記のソースでポイントになるのが、Modelを変更しても、画面は自動で更新されない(Viewを手動で更新)という点です。

毎回「画面を更新してね」と書く必要があるんです。

これがMVCの「手動でつなぐ設計」ってやつですね。

ASP.NetにおけるMVCの考え方も参考になるかもしれません

なぜMVCでは限界があるのか

ではなぜMVCでは限界があるのか?

シンプルな画面であれば、MVCでも問題ありません。

ただ、業務システムのように多岐にわたる処理が存在し、画面が複雑になると厳しくなってきます。

更新処理が増える

・入力項目が増える
・一覧表示が増える
画面同士の連携が増える

先ほどのコード例にも表示したように、更新のたびに手動で処理を書く必要があります。

保守性が下がる

・Viewを変えるとControllerも修正
・Modelを変えてもController修正

Aを修正するとBも修正、Cを修正するとBも修正、、、といったように影響範囲が広くなってしまいます。

このあたりは、実務で触っていると一度は感じるポイントではないでしょうか。

MVVMとは何か ― 自動でつながる設計

こうした問題を解決するために登場したのがMVVMです。

MVVM(Model-View-ViewModel)は、UI(画面)とロジックを分離するための設計パターンです。
特にWPFのようなデータバインディングを前提としたフレームワークで多く採用されています。

MVCでは、ControllerがModelとViewの間に入り、状態の変化を手動で画面へ反映していました。
一方MVVMでは、この「手動更新」をなくし、状態(データ)を変更するだけで、UIが自動で更新されるという仕組みを採用しています。

MVVMのドキュメントはこちら

MVVMの構成と流れ

・Model:データ
・View:画面(Xaml)
・ViewModel:橋渡し

そして、以下がMVVMの処理フローのイメージとなります。

①ユーザーが入力(View)

②値がViewModekに反映(Binding)

③ViewModelで処理実行

④プロパティ更新

⑤Uiが自動更新(Binding)

View ←→ ViewModel ←→ Model

Binding(自動同期)

といった感じです。

そして最大の特徴が、データバインディング(Binding)です。

データバインディングによってUIとViewModelが紐づいているため、値を変更するだけで自動的に画面へ反映されます。

といってもまだイメージが付かないと思うので実際に簡単な処理とソースを書いていきたいと思います。

ユーザー操作から画面更新までの流れ(コードで理解する)

ここではユーザー操作から画面更新までの流れ(コードで理解する)

ViewModel

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

public class MainViewModel : INotifyPropertyChanged
{
private string name;
private string message;

public string Name
{
get => name;
set
{
name = value;
OnPropertyChanged();
}
}

public string Message
{
get => message;
set
{
message = value;
OnPropertyChanged();
}
}

public ICommand ShowMessageCommand { get; }

public MainViewModel()
{
ShowMessageCommand = new RelayCommand(ShowMessage);
}

private void ShowMessage()
{
Message = $"こんにちは、{Name}さん";
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

XAML(View)

<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>

<StackPanel Margin="20">

<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />

<Button Content="表示" Command="{Binding ShowMessageCommand}" />

<TextBlock Text="{Binding Message}" />

</StackPanel>

動きのポイントとしては

・入力 ⇒ 自動でNameに反映
・ボタン ⇒ Command実行
・Message変更 ⇒ UI自動更新

このように、「値を変えるだけでUIが更新される」ため、更新処理を個別に書く必要がなくなり、状態の不整合を防ぐことができます。

WPFとMVVMの関係 ― なぜこの組み合わせなのか

さて、ここまで長かったですがようやくWPFの話に入ります。

WPF(Windows Presentation Foundation)は、Microsoftが提供するデスクトップアプリケーション向けのUIフレームワークです。

最大の特徴はUIとデータを結びつける「データバインディング」が標準で備わっていることです。

従来のUI開発では、

  • 値を取得する
  • UIに反映する

といった処理をコードで書く必要がありました。

しかしWPFでは、XAMLでUIを宣言し、Bindingによってデータと接続することで、UIの更新を仕組みで自動化することができるのです。

WPFの特徴

・XamlでUIを定義できる
Bindingが標準で使える
・DataContextでデータを紐づける

ちなみにDataContextとは、UIコントロールが持つプロパティで、「このコントロールはどのデータオブジェクトを参照するか」を指定することができます。

なぜMVVMが合うのか

先ほどの章でもお話した通りWPFはデータバインディングによるUI更新を前提として設計されています。

そのため、

・UIはXAMLで定義する
・ロジックはViewModelで管理する
・Bindingで両者を接続する

というMVVMの構造が自然に当てはまります。

片やMVCのようにControllerで画面更新を行う設計では、

・更新処理が増える
・ロジックが分散する

といった問題が発生してしまう。。

そんなロジックが増える(バグの温床)悩みの種を、MVVMだと状態の変化=UIの変化という構造のおかげで解消できちゃうという感じです。

まとめ

色々と話してきましたがMVCとMVVMの違いについて、以下のことだけでも理解してもらえたら幸いです。
・MVC:操作をつなぐ設計(手動)
・MVVM:状態を同期する設計(自動)

MVCはシンプルで分かりやすい一方で、画面の規模が大きくなるにつれて状態管理が複雑になりやすいという側面があります。
それに対してMVVMは、データバインディングによって状態とUIを自動で同期させることで、更新処理の負担を軽減し、構造をシンプルに保つことができます。

そしてWPFは、この「自動同期」を前提として作られているため、MVVMとの相性が非常に良いフレームワークです。

最初は抽象的に感じるかもしれませんが、 「UIを操作する」のではなく「状態を変更することでUIを変える」という視点に切り替えることが、理解の大きなポイントです。

MVVMは決して特殊な設計ではなく、UIをよりシンプルに扱うための考え方の一つです。
まずは小さな画面から実際に触れてみることで、そのメリットを実感できると思います。