nuits.jp blog

C#, Xamarin, WPFを中心に書いています。Microsoft MVP for Development Technologies。

INotifyPropertyChangedをFody使って実装する:VS4Mac編

なんか20番煎じくらいな気がしますが、INotifyPropertyChangedを実装しようとするとフィールドやプロパティや変更通知やら、諸々実装が大変だ!というのがありますよね。これの簡単な解決策としては大きく二つはあると思っています。

  • ReactivePropertyを利用する
  • PropertyChanged.Fodyを利用する

前者はReactiveプログラミングをしないのであればオーバースペックな気がします。そこでFodyを利用する方法が検討対象になってきます。この辺りの詳細は次の記事に良くまとまっているように思います(全部目を通しきれていませんが)。

qiita.com

ただTeratailでVS4Macでうまくいかな〜いという声があったので、簡単な手順をまとめました。なお実際の実現方法は他にもパターンがありますが、細かいことは頑張って本家の英語を読みましょう。

動くコードはGithubに置いておきましたので確認してください。

github.com

それでは簡単に説明していきます。

パッケージを適用する

.NET Standardの共通コードが登録されているプロジェクトにNuGetからPropertyChanged.Fodyをインストールしましょう。

f:id:nuitsjp:20180831230033p:plain

その他のプロジェクトに当てる必要はありません。

FodyWeavers.xmlを追加する

Fody系のライブラリを利用するときのお作法なのですが、プロジェクトのルートフォルダにFodyWeavers.xmlファイルを置いて、その中に適用するFody系ライブラリを指定します。今回は次のように記載しましょう。

f:id:nuitsjp:20180831231125p:plain

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
  <PropertyChanged/>
</Weavers>

ViewModelを実装する

MainPageViewModel.csを作成し、次のように実装しましょう。

using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;

namespace HelloFody
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public string Message { get; set; } = "Hello, Fody!";

        public ICommand UpdateMessage => new Command(() => Message = "Updated Message!!");

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

そしてこのViewModelをViewに適用します。MainPage.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:local="clr-namespace:HelloFody" 
             x:Class="HelloFody.MainPage">
    <ContentPage.BindingContext>
        <local:MainPageViewModel/>
    </ContentPage.BindingContext>
    <StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center">
        <Label Text="{Binding Message}"/>
        <Button Text="Update message." Command="{Binding UpdateMessage}"/>
    </StackLayout>
</ContentPage>

大きな改修は3点。

  1. BindingContextにMainPageViewModelを設定するように変更
  2. LabelのTextをリテラルからViewModelのMessageプロパティを表示するように変更
  3. Buttonを追加し、押下されたらMessageを更新するようCommandをバインド

動作確認

起動すると、まずは次のような画面が表示されます。

f:id:nuitsjp:20180831231150p:plain

そしてボタンを押すとメッセージが更新されます。

f:id:nuitsjp:20180831231215p:plain

ViewModelのプロパティは次のように実装しています。

        public string Message { get; set; } = "Hello, Fody!";

通常では更新されても通知されないはずですが、動作から見てちゃんと変更通知が投げられていることが見て取れるでしょう。

以上です。