[C#] INotifyPropertyChangedを楽に実装し、ReSharperのTemplateも作る

2018-05-12 (土)

BindableBaseという基底クラスを用意し、継承して簡単に使用します。
ReSharperのテンプレート(スニペット)も用意して、記述も楽にします。

環境

  • Windows 10 Pro 64bit 1709
  • Visual Studio Community 2017 15.5.7
  • .NET Framework 4.6.1
  • C# 7.0
  • ReSharper 2018.1

結果

実装

WPFで実装したサンプルソースはこちら
https://github.com/dokeep/csharp-bindablebase

BindableBase.cs

INotifyPropertyChangedを実装した基底クラスを用意します。

public class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        return SetProperty(ref field, value, null, propertyName);
    }

    protected virtual bool SetProperty<T>(ref T field, T value, Action onChanged, [CallerMemberName]string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;

        field = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

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

Sample.cs

実際に使用するクラスを作ります。以下の(例1)(例2)は使い分けます。

public class Sample : BindableBase
{
    public int Age
    {
        get => _age;
        set => SetProperty(ref _age, value);
    }
    private int _age;

    public string Name
    {
        get => _name;
        // (例1) PropertyChangedが "Name" -> "FullName" の順に発生する例
        set
        {
            if (SetProperty(ref _name, value) OnPropertyChanged(nameof(FullName)));
        }
        // (例2) PropertyChangedが "FullName" -> "Name" の順に発生する例
        set => SetProperty(ref _name, value, () => OnPropertyChanged(nameof(FullName)));
    }
    private string _name;

    public string FullName => $"Sample {Name}";
}

ReSharperのTemplateを作成

以下の3つのテンプレートをExportしたファイルはこちら。Importできます。
https://github.com/dokeep/csharp-bindablebase/blob/master/CsBindableBase/ReSharper/BindableBase.DotSettings

作成手順

メニューからReSharper -> Tools -> Templates Explorer...を開きます。

New Templateボタンで以下の3つのテンプレートを作成します。
その後に3つのテンプレートを選択して、New Category...ボタンでBindableBaseというカテゴリを付けておきます。

ppa

public $TYPE$ $PROPERTY$
{
    get => _$FIELD$;
    set => SetProperty(ref _$FIELD$, value, () => $ACTION$);
}
private $TYPE$ _$FIELD$;

ppf

public $TYPE$ $PROPERTY$
{
    get => _$FIELD$;
    set
    {
        if (SetProperty(ref _$FIELD$, value))
        {
            $ACTION$
        }
    }
}
private $TYPE$ _$FIELD$;

ppp

public $TYPE$ $PROPERTY$
{
    get => _$FIELD$;
    set => SetProperty(ref _$FIELD$, value);
}
private $TYPE$ _$FIELD$;

感謝

2018-05-12 (土)