C# クラス内の全ReactivePropertyのSubscribeに同じメソッドを登録する
やり方を拝借したのはここ:
https://tamafuyou.hatenablog.com/entry/2016/10/29/020651
感謝感激です!ココが無ければ諦めてた…ってわけで、詳しくは上記ブログを見てね!(投げやり)
ただ、自分のやりたい事をやろうとしたとき、「どうにかならんかなぁー」って感じ
現状:
1.DataクラスにReactiveProperty を沢山保持(DBやらCSVなどのデータをまとめたいから)
2.DataクラスのReactiveProperty を画面に直接参照させてる。(ViewMode内のプロパティがたくさんできるのが嫌)
3.データを1つのダイアログ内で全部表示・編集させてる
やりたい事:
・ユーザが変更した時は「保存ボタン」を押せなくするが、「別名保存ボタン」は押せるようにしたい。
ってなるので、Dataクラス内の全ReactivePropertyに同じSubscribeを登録したかった。
エラーの有無は「ObserveHasErrors」と「CombineLatest」を全部チェックさせるしかないけど、
Subscribeを全部登録するのは面倒すぎたので探してた。
で、こうなった
使い方はこんな感じ:
これで、全てのReactivePropertyの変更通知をSampleメソッドで一括処理できるようになりました。
データの差分が無いかを確認し、ReactiveProperty<bool> に値を保持すれば、ボタン制御に使える!
しかし、PropertyInfo から ReactiveProperty にキャスト(isやas)出来ないっぽいので、大変ですな…
まぁ、画面と1対1のデータのはずだからこんなことする方が少ないんだろうけどね。
後、ダイアログで使ってるから、ダイアログ破棄時に「DisposeSubscribeAllReactiveProperty」メソッドの呼び忘れをしなければ良いかなと…
メモリリークしてないよな…多分…自己責任で!
検索用:C# WPF ReactiveProperty Subscribe 全部 全て 同じメソッド 登録 追加 設定 一括 変更通知
https://tamafuyou.hatenablog.com/entry/2016/10/29/020651
感謝感激です!ココが無ければ諦めてた…ってわけで、詳しくは上記ブログを見てね!(投げやり)
ただ、自分のやりたい事をやろうとしたとき、「どうにかならんかなぁー」って感じ
現状:
1.DataクラスにReactiveProperty を沢山保持(DBやらCSVなどのデータをまとめたいから)
2.DataクラスのReactiveProperty を画面に直接参照させてる。(ViewMode内のプロパティがたくさんできるのが嫌)
3.データを1つのダイアログ内で全部表示・編集させてる
やりたい事:
・ユーザが変更した時は「保存ボタン」を押せなくするが、「別名保存ボタン」は押せるようにしたい。
ってなるので、Dataクラス内の全ReactivePropertyに同じSubscribeを登録したかった。
エラーの有無は「ObserveHasErrors」と「CombineLatest」を全部チェックさせるしかないけど、
Subscribeを全部登録するのは面倒すぎたので探してた。
で、こうなった
/// <summary>
/// 画面データクラスの元
/// </summary>
[DataContract]
public abstract class AbstractBase
{
/// <summary>
/// 全てのReactiveProperty に Subscribeを追加します
/// </summary>
/// <param name="action">値変更時に呼び出されるメソッド<名称, 値></param>
public void SubscribeAllReactiveProperty(Action<object, string, object> action)
{
var disposes = this.GetType()
.GetProperties()
.Where(x =>
x.PropertyType.Name.StartsWith(nameof(ReactiveProperty)) ||
x.PropertyType.Name.StartsWith(nameof(ReadOnlyReactiveProperty)))
.Select(x =>
System.Linq.Expressions.Expression.Lambda(System.Linq.Expressions.Expression.Call(this.GetType(),
nameof(RelaySubscribe),
new[] { x.PropertyType.GetGenericArguments().First() },
System.Linq.Expressions.Expression.Constant(x.GetValue(this)),
System.Linq.Expressions.Expression.Constant(x.Name),
System.Linq.Expressions.Expression.Constant(action)))
.Compile().DynamicInvoke() as IDisposable)
.ToList();
}
/// <summary>
/// 全てのReactiveProperty に subscribe を登録します
/// </summary>
/// <typeparam name="TT">ReactivePropertyの型</typeparam>
/// <param name="source">ReactiveProperty</param>
/// <param name="name">プロパティ名称</param>
/// <param name="action">呼び出すアクション</param>
/// <returns></returns>
public static IDisposable RelaySubscribe(IObservable source, string name, Action<object, string, object> action)
{
return source.Subscribe(x =>
{
action(source, name, x);
});
}
/// <summary>
/// Subscribeの登録を破棄します
/// </summary>
public void DisposeSubscribeAllReactiveProperty()
{
if (SubscribePropertys != null)
{
foreach (var tmp in SubscribePropertys)
{
tmp.Dispose();
}
}
}
}
使い方はこんな感じ:
public ReactiveProperty<SettingData> SettingData { get; set; }
public コンストラクタ(SettingService settingService){
SettingData = settingService.SettingData;
SettingData.Value.SubscribeAllReactiveProperty(Sample);
}
private void Sample(object sender, string name, object value)
{
// いずれかのプロパティで変更があった時の処理
}
これで、全てのReactivePropertyの変更通知をSampleメソッドで一括処理できるようになりました。
データの差分が無いかを確認し、ReactiveProperty<bool> に値を保持すれば、ボタン制御に使える!
しかし、PropertyInfo から ReactiveProperty にキャスト(isやas)出来ないっぽいので、大変ですな…
まぁ、画面と1対1のデータのはずだからこんなことする方が少ないんだろうけどね。
後、ダイアログで使ってるから、ダイアログ破棄時に「DisposeSubscribeAllReactiveProperty」メソッドの呼び忘れをしなければ良いかなと…
メモリリークしてないよな…多分…自己責任で!
検索用:C# WPF ReactiveProperty Subscribe 全部 全て 同じメソッド 登録 追加 設定 一括 変更通知
コメント
コメントを投稿