やり方を拝借したのはここ:
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 全部 全て 同じメソッド 登録 追加 設定 一括 変更通知