ViewModelのバインディングプロパティを定義する場合にViewへの通知処理が存在する為、プロパティの定義がめんどくさくなります。
それを簡単に書く方法を記します。
また下記方法によりプロパティの解放を一括で行う為、メモリリークするコマンド等も解放されます。
BindingModel (画面通知するモデル)に下記内容を追加します。
プロパティを格納する箱を用意します。
public abstract class BindingModel : BaseModel
{
// プロパティを管理する箱
private Dictionary Propertys { get; set; } = new Dictionary();
}
{
// プロパティを管理する箱
private Dictionary
}
次にGetプロパティを作成します。
protected T Get<T>([CallerMemberName] string name = null)
{
// プロパティ名が無い場合はデフォルト値を返します。
if (string.IsNullOrEmpty(name) == true)
{
return default(T);
}
// プロパティリストが無い場合はデフォルト値を返します。※Dispose時に発生する場合あり
if (this.PropertieItems == null)
{
return default(T);
}
// プロパティリストから名前が同一の情報を取得し返します。
object value = null;
if (this.PropertieItems.TryGetValue(name, out value) == true)
{
return value == null ? default(T) : (T)value;
}
// プロパティリストに名前が同一の情報が無い時、デフォルト値を返します。
return default(T);
}
{
// プロパティ名が無い場合はデフォルト値を返します。
if (string.IsNullOrEmpty(name) == true)
{
return default(T);
}
// プロパティリストが無い場合はデフォルト値を返します。※Dispose時に発生する場合あり
if (this.PropertieItems == null)
{
return default(T);
}
// プロパティリストから名前が同一の情報を取得し返します。
object value = null;
if (this.PropertieItems.TryGetValue(name, out value) == true)
{
return value == null ? default(T) : (T)value;
}
// プロパティリストに名前が同一の情報が無い時、デフォルト値を返します。
return default(T);
}
次にSetプロパティを作成します。
protected void Set<T>(T value, [CallerMemberName] string name = null)
{
// プロパティ名が無い場合は処理を終了します。
if (string.IsNullOrEmpty(name) == true)
{
return;
}
// プロパティリストが無い場合は処理を終了します。※Dispose時に発生する場合あり
if (this.PropertieItems == null)
{
return;
}
// プロパティが存在するかチェックします。
if (this.Propertys.ContainsKey(name) == false)
{
// キーが存在しない時、プロパティリストに追加します。
this.Propertys.Add(name, value);
// プロパティ変更通知を発生させます。
this.NotifyPropertyChanged(name);
}
else
{
// キーが存在する時、値を変更します。
if (Equals(value, this.Get(name)))
{
// 同一の値の場合は処理を終了します。
return;
}
// プロパティの値を置き換えます。
this.Propertys[name] = value;
// プロパティ変更通知を発生させます。
this.NotifyPropertyChanged(name);
}
}
{
// プロパティ名が無い場合は処理を終了します。
if (string.IsNullOrEmpty(name) == true)
{
return;
}
// プロパティリストが無い場合は処理を終了します。※Dispose時に発生する場合あり
if (this.PropertieItems == null)
{
return;
}
// プロパティが存在するかチェックします。
if (this.Propertys.ContainsKey(name) == false)
{
// キーが存在しない時、プロパティリストに追加します。
this.Propertys.Add(name, value);
// プロパティ変更通知を発生させます。
this.NotifyPropertyChanged(name);
}
else
{
// キーが存在する時、値を変更します。
if (Equals(value, this.Get(name)))
{
// 同一の値の場合は処理を終了します。
return;
}
// プロパティの値を置き換えます。
this.Propertys[name] = value;
// プロパティ変更通知を発生させます。
this.NotifyPropertyChanged(name);
}
}
最後にまとめてプロパティを解放する処理を記述します。
protected override void Dispose(bool disposing)
{
// 終了処理中の時は処理を行わない。
if (base.Disposed == false)
{
// プロパティを全て解放する。
this.Propertys?.RemoveAll();※
this.Propertys = null;
// ベースのDisposeを呼び出す。
base.Dispose(disposing);
}
}
{
// 終了処理中の時は処理を行わない。
if (base.Disposed == false)
{
// プロパティを全て解放する。
this.Propertys?.RemoveAll();※
this.Propertys = null;
// ベースのDisposeを呼び出す。
base.Dispose(disposing);
}
}
※RemoveAllは拡張メソッドでIDisposable属性のものを探しDisposeを実行する処理を自作したものです。
使用例
public void TestViewModel : BindingModel
{
// バインディングプロパティ
public int Code
{
get { base.Get<int>(); }
set { base.Set(value); }
}
}
{
// バインディングプロパティ
public int Code
{
get { base.Get<int>(); }
set { base.Set(value); }
}
}
上記のようにバインディングプロパティがすっきりします。