はじめに
ある程度大きなGUIを持つソフトウェアを開発する場合、
開発を容易にするために何らかのデザインパターンに基づいて開発することが多いです。
ソフトウェアを開発する際に使用するデザインパターンとしては
MVC (Model-View-Controller)やMVVM (Model-View-ViewModel)などがあります。
当然、OSやプログラミング言語固有の機能のみで、これらのデザインパターンを実現できます。
ただ、何らかのフレームワークを使用するほうがデザインパターンを楽に実現できます。
PrismはXamarinでMVVMを実現するためのフレームワークです。
MVVMについて
MVVMはModel, View, ViewModelの3層で構築されます。
それぞれの項目を簡単に説明すると、
- Model
GUIの描画には関係ないデータの読み書き、編集、保持等を行う層
- View
GUIを描画する層
ViewModelを参照する
- ViewModel
ViewがGUIの描画をするために必要な情報を保持、生成する層
Modelを参照する
と役割が分かれてます。
参照は一方方向のみで、ModelはViewModelを見ないし、ViewModelはViewを見ません。
お互いの役割を分離することで保守性を高めやすくします。
Xamarinでは、ViewはXamlとその拡張、ViewModelはXamlにバインディングされるインスタンス、Modelはそれ以外になります。
勘違いされやすい点としてModelは描画をしないだけで、描画に関係する情報を持っても問題ないということがあります。
例えば、ユーザーが設定した文字の色を保存したり読み込んだりする機能はModelが持ちます。
これらの情報を伝達するのがViewModelです。
当然、設定が固定されている場合、Viewに色の情報があっても問題ありません。
また、デザインパターンを正しく用いて開発する方法は小規模な開発には向かないことが多いです。
全体のソースコードが冗長であり、設計に従う必要もあるので、直接Viewに機能を書いたほうが早いです。
ただ、当然、ViewにModelのコードを書くとテストの自動化がしにくかったり、規模が大きくなるとコードが複雑化しがちです。
そのような問題が発生する規模の開発でフレームワークの力が発揮されます。
それでは、Prismの機能について説明していきます。
BindableBase
xamlでクラスをバインドするのに便利な機能が予め実装されたクラスです。
xamlでバインドする場合、INotifyPropertyChangedで定義されたメソッドを実装する必要があります。
Prismを使用しない場合、各個人が独自で使いやすく実装することが多いです。
ただ、それでは使用方法が統一されてなく、他の人に理解されにくいという問題があります。
そこで、BindableBaseを使うことで個人に依存しないバインドのためのクラスを実現できます。
SetPropertyがBindableBaseで実装されているメソッドです。
他にもありますが、それは他のサイトを参照するようお願いします。
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
namespace prismSample.ViewModels
{
public class MainPageViewModel : BindableBase, INavigationAware
{
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainPageViewModel()
{
}
}
}
ViewModelLocator.AutowireViewModel
PrismにはViewとViewModelを結びつける機能があります。
それがViewModelLocator.AutowireViewModelです。
クラス名に従って自動的にViewとViewModelを結びつけます。
例えば、Prj.Views.SampleWindow
とPrj.ViewModels.SampleWindowViewModel
がある場合、この2つを結びつけます。
xamlで下記のように定義することで有効になります。
xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="prismSample.Views.MainPage" Title="MainPage">
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="{Binding Title}" />
</StackLayout>
</ContentPage>
実はPrism6.2からデフォルトがTrueになったので、assembly=Prism.Forms"
さえ記述すれば動くはずですが分かりやすくするために全て明示してます。
当然、下記のようにBindingContextにViewModelのインスタンスを代入することで同じことを実現できます。
ただ、自動的にViewとViewModelが結びつくようにすると、必ず一対一でViewとViewModelが存在することを明示できて
他の開発者が理解しやすくなります。
using Xamarin.Forms;
namespace prismSample.Views
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new ViewModels.MainPageViewModel();
}
}
}
最後に
どんどん色んな機能を説明していきます。