INotifyPropertyChanged実装のありえない面倒くささと、ReactivePropertyの信じられない素晴らしさ


# 期待
MVVMや双方向バインディングでは、バインドしたViewModelの更新を画面に反映して欲しいです。
そのような場合、ViewModelにINotifyPropertyChangedインターフェイスを実装して実現するようです。

# INotifyPropertyChangedを実装する方法


[方法 : INotifyPropertyChanged インターフェイスを実装する](https://msdn.microsoft.com/ja-jp/library/ms229614(v=vs.110).aspx)に、従って実装します。

```cs:ViewModel.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfApplication1
{
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private string message = "";
        public string Message
        {
            get
            {
                return this.message;
            }
            set
            {
                if (value != this.message)
                {
                    this.message = value;
                    NotifyPropertyChanged();
                }
            }
        }
    }
}
```

次のような気持ちでいっぱいです。

- PropertyChangedEventHandlerとNotifyPropertyChangedのおまじない感
- 自動実装プロパティーで、プロパティーを簡潔に書けるC#の魅力とはなんだったのか？
- （必要な場合）さらにModelとの変換ロジックも実装するの？
- こんなことで「ViewModelを書けば、（ビューの）データと描画ロジックを美しく分離できる」と言えるのか？


```cs:MainWindow.xaml.cs
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = new ViewModel();

            DataContext = vm; // DataContextにViewModelをバインド
            vm.Message = "Hello"; // DataContextのプロパティーを更新すると画面に反映
        }
    }
}
```

```xaml:MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Text="{Binding Message}"/>
    </Grid>
</Window>
```

こちらは期待通りです。

# スクリーンショット
実行すると、こんな感じです。
![スクリーンショット 2015-10-20 22.34.20.png](https://qiita-image-store.s3.amazonaws.com/0/15964/38e4e7a9-7c08-c629-1c01-c65815cce93d.png "スクリーンショット 2015-10-20 22.34.20.png")

# 軽減手段
いくつか多少軽減する方法はあるようです。

- [INotifyPropertyChangedのいけてる実装 - かずきのBlog@hatena](http://blog.okazuki.jp/entry/20091214/1260803280)
- [INotifyPropertyChanged の実装 | ++C++; // 未確認飛行 C ブログ](https://ufcpp.wordpress.com/2009/12/28/inotifypropertychanged-%E3%81%AE%E5%AE%9F%E8%A3%85/)


データクラスとして非本質的な記述が、あまり減らないのが気になります。

# ReactivePropertyを使うと

```cs:ViewModel.cs
using Reactive.Bindings;

namespace WpfApplication1
{
    public class ViewModel
    {
        public ReactiveProperty<string> Message { get; } = new ReactiveProperty<string>();
    }
}
```

この簡潔さ。データクラスがプロパティー定義だけを持つ、圧倒的な簡潔さです。
型名は少し長いですが、VisualStudioの補完機能を考えれば気になりません。

```cs:MainWindow.xaml.cs
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = new ViewModel();

            DataContext = vm; // DataContextにViewModelをバインド
            vm.Message.Value = "Hello"; // DataContextのプロパティーを更新すると画面に反映
        }
    }
}
```

```xaml:MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Text="{Binding Message.Value}"/>
    </Grid>
</Window>
```

値の参照・設定に`Value`を使う点に注意が必要です。
はじめて試した時、見事にはまりました。

# リンク
- [MVVMとリアクティブプログラミングを支援するライブラリ「ReactiveProperty v2.0」オーバービュー - かずきのBlog@hatena](http://blog.okazuki.jp/entry/2015/02/22/212827)
- [ReactiveProperty オーバービュー - かずきのBlog@hatena](http://blog.okazuki.jp/entry/2014/05/07/014133)