kazuakix の日記

Windows Phone とか好きです

Windows Phone アプリで Prism を使ってみる

以前から自分の作るアプリの設計が汚いことに悩んでいたので Prism を使って矯正していこうと思います。

準備

NuGet で Prism.StoreApps をインストールします。

f:id:kazuakix:20141016235725j:plain,w500

普通の Prism ではないので注意してください。(しばらく悩みました)
 

App.xaml の修正

App の基底クラスを Application から MvvmAppBase に変更します。

まずは App.xaml を修正します。

<prism:MvvmAppBase
    x:Class="App19.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:prism="using:Microsoft.Practices.Prism.StoreApps"
    xmlns:local="using:App19">

</prism:MvvmAppBase>

 
続けて App.xaml.cs を修正します。

f:id:kazuakix:20141016235737j:plain,w500

基底クラスを変更した後、OnLaunched と OnSuspending メソッド 及びそれらから参照されているメソッド・メンバ変数をサックリ削除します。

結局 残ったのはコンストラクタだけ...

public App()
{
    this.InitializeComponent();
}

 
OnLaunchApplicationAsync をオーバーライドして最初のページ (View) への移動コードを追加します。

protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
    this.NavigationService.Navigate("Main", null);
    return Task.FromResult<object>(null); 
}

移動先のページとして後で MainPage というクラスを作るのですが、Navigate メソッドに指定するのはクラス名から Page を除いた名前になります。

また、return Task.FromResult(null); という一瞬??な記述がありますが、これは OnLaunchApplicationAsync が Task を返すことを強要しているのでダミーとして返しているのだそうです。もう少し短く書くなら return Task.FromResult(0); とかでしょうか?
 

ページ (View) の作成

プロジェクト直下に Views フォルダを作って、その中に MainPage.xaml を作成します。元々の MainPage.xaml は不要なので削除しましょう。

f:id:kazuakix:20141016235747j:plain

View は VisualStateAwarePage が基底クラスになります。

<prism:VisualStateAwarePage
    x:Class="App19.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App19.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:prism="using:Microsoft.Practices.Prism.StoreApps"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
    </Grid>
</prism:VisualStateAwarePage>
public sealed partial class MainPage : VisualStateAwarePage
{
    public MainPage()
    {
        this.InitializeComponent();
    }

 
ところで、参考資料を見てみると View と ViewModel の関連付けのために XAML で ViewModelLocator.AutoWireViewModel="true" とするように書かれています。
でも、実際に実行すると "Your views must implement IView" という警告が出てくるので(動作には影響ありませんが)コードビハインドで関連付けを行いました。

f:id:kazuakix:20141016235755j:plain

public sealed partial class MainPage : VisualStateAwarePage
{
    public MainPage()
    {
        this.InitializeComponent();
        ViewModelLocator.SetAutoWireViewModel(this, true);
    }

 

ViewModel の作成

プロジェクト直下に ViewModels フォルダを作って View 名 + ViewModel (今回は MainPageViewModel) という名前でクラスを作ります。
基底クラスは Microsoft.Practices.Prism.Mvvm.ViewModel になります。

適当にプロパティを作ってみました。

class MainPageViewModel : ViewModel
{
    private string _message;
    public string Message
    {
        get { return this._message; }
        set { this.SetProperty(ref this._message, value); }
    }

    public MainPageViewModel()
    {
        this.Message = "こんにちは Prism さん";
    }
}

INotifyPropertyChanged 関係の処理が SetProperty 一発でできるようになっています。(サンプルプロジェクトでよく見かけるつくりですね)
 

動かしてみる

ViewModel の内容を表示できるように View を変更します。

<Grid>
    <TextBlock Text="{Binding Message}" Style="{StaticResource BodyTextBlockStyle}" />
</Grid>

実行してみるとこの通り。

f:id:kazuakix:20141016235801j:plain

特別 View と ViewModel の関連付けなどは行っていませんが、ちゃんと内容が表示されていますね。