Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetValidateAttribute()とウィンドウ表示前のバリデーション(WPF) #85

Closed
toras9000 opened this issue Sep 17, 2018 · 8 comments

Comments

@toras9000
Copy link

いつも ReactiveProperty 利用させていただいております。

WPFで利用した際のバリデーションに関する点です。

デフォルトコンストラクタでReactivePropertyを生成し、属性とSetValidateAttribute()を利用してバリデーションを設定にした際、ウィンドウの表示前にプロパティ値を変更してもUI側に反映されない事象があります。
事象発生のコード例は以下のようなものです。
(SomeFuncWindowViewModel.cs 内に上述の事象に該当するコードを記載しています)
https://github.com/toras9000/RxPropValidation

自分で調べた限りでは、ErrorsChangedイベントの通知タイミングが関係していると思われました。
ReactivePropertyのコンストラクタにImmidiateSchedulerを指定した場合は問題なく状態が反映されます。
あるいはデフォルトコンストラクタのままで、自前ビルドでSetValidateAttribute()内のErrorsChanged通知時スケジューラをImmidiateSchedulerにしたものを利用した場合も正常に反映されました。
(デフォ設定の場合にどういう理由で正常に反映されないのかまでは不明ですが)

ErrorsChangedイベントの通知はスケジューラを通さなくてもよいのではないかとも思うのですが、ほんとに良いのかはっきりわからないのと、従来との互換も保つ意味でSetValidateAttribute()にスケジューラを受け取るオーバーロードを追加すれば柔軟に対処できるのではと思いましたが、いかがでしょうか。

自分では上記のように考えてみましたが、その考え方も正しいかどうか確信もありませんので、上記事象についてご確認いただければと思います。

@runceel
Copy link
Owner

runceel commented Oct 2, 2018

返事が遅くなりすいません。
見てみましたが原因は、ぱっとわかりませんでした。

もうちょっと時間のあるタイミングで時間をとってみてみます。

@runceel
Copy link
Owner

runceel commented Oct 17, 2018

もう少し見てみたのですが問題の起きている Window を表示したあと個々の TextBox の Validation.HasError 添付プロパティを確認したら、どちらも False になっていました。

ためしに、ReactivePropertyではない普通のプロパティで変更通知とエラー状態の変更通知を UI スレッドに Dispatcher を使って発行するようなプロパティを作ってみたところ、Text2 と同じ挙動をしました。

どうも WPF がそういう動きをするみたいです。

@toras9000
Copy link
Author

ご確認ありがとうございます。

やはりそのようですよね。
INotifyPropertyChanged.PropertyChanged と INotifyDataErrorInfo.ErrorsChanged が連続で通知されないと正常に認識してくれないように見えます。
SetValidateAttribute()のソースを参照したところReactivePropertyのコンストラクタに指定したスケジューラを使ってErrorsChangedも通知しているようでしたので、両イベントを連続的に通知してもらうためにサンプルのText1ではImmediateScheduler.Instanceを指定しました。

しかし、やはりPropertyChangedのためにUIDispatcherScheduler.Defaultを利用したい場合がほとんどだと思いますので、以下のような形でErrorsChangedの通知にだけImmediateSchedulerができるようになれば良いのではないだろうか、というのが当方の問題回避案になります。

this.Text = new ReactiveProperty(UIDispatcherScheduler.Default)
.SetValidateAttribute(() => this.Text1, ImmediateScheduler.Instance);

単にまず思いついたのがこれというだけで、他に対処方法があれば上記以外の方法でも良いのですが、うまく問題回避できる手段があってほしいと思った次第です。

@runceel
Copy link
Owner

runceel commented Nov 8, 2018

暫く考えてみたのですが、その解決方法だと UI スレッド以外から値を更新したときに ErrorsChanged イベントが UI スレッド以外で起きてしまうような気もするのですがどうでしょうか??

その場合、エラーにならないかなというのが心配です。

@toras9000
Copy link
Author

すみません、値の変更を購読したコンテキストからErrorsChangedの発行処理をしていると思い込んでいましたが、そうではなかったですね。
失礼しました。ご指摘の通りですね。

@runceel
Copy link
Owner

runceel commented Nov 12, 2018

なにかいい解決方法はないものかと思うのですが、なかなかこれといっては思いつかないですね…。

@runceel
Copy link
Owner

runceel commented Aug 7, 2020

WPF の挙動に起因するものなのでいったんクローズにしておきます。

@runceel
Copy link
Owner

runceel commented Apr 26, 2021

@toras9000
FYI & 超亀レスですが、上の関連 issue のほうで、この問題解決しそうです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants