Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Why WhenAnyValue stops working after using SuppressChangeNotifications?#3830

Unanswered
sinatrocious asked this question inQ&A
Discussion options

I have reactive object and monitoring for its reactive properties usingWhenAnyValue. It works until I useSuppressChangeNotifications once. Then it become broken and I am trying to figure out what to do:

reactive bug

Show/hide repro
publicclassMainViewModel:ReactiveObject{[Reactive]publicstring?Text{get;set;}[Reactive]publicboolValue{get;set;}publicReactiveCommand<Unit,Unit>Test{get;}publicMainViewModel(){this.WhenAnyValue(o=>o.Value).Subscribe(value=>Text=value.ToString());Test=ReactiveCommand.Create(()=>{usingvardispose=this.SuppressChangeNotifications();Value=true;});}}
    <StackPanel>        <CheckBoxContent="{Binding Text}"IsChecked="{Binding Value}"/>        <ButtonContent="Test"Command="{Binding Test}"/>    </StackPanel>

After clickingTest button the checkbox is not updated for several clicks. How to fix this?

In real project there are many properties monitored in several places outside and I need to silently update them (load values without anyone noticing the changes) and I don't want to introducebool IgnoreChanges and use it everywhere. This is where I was hopingSuppressChangeNotifications will work, but there is something like caching values and skipping emitting going on as it seems. Any easy workaround?

You must be logged in to vote

Replies: 2 comments 8 replies

Comment options

I'm confused as to what you're finding unexpected here - you are suppressing change notifications, they shouldn't fire!

You must be logged in to vote
1 reply
@sinatrocious
Comment options

I expect to see "True" text when checkbox is checked or "False" text when it's unchecked. That's not true fortwo clicks after suppression.

Put 3 breakpoints: one in value setter (V), one in text setter (T), one in subscribe (S).

  1. Click checkbox - VST
  2. Click checkbox - VST
  3. ClickTest button - V
  4. Click checkbox - V
  5. Click checkbox - V
  6. Click checkbox - VST

Why 4 and 5 step are so strange?

Comment options

You are waiting for Garbage Collection to remove the Suppression after clicking the button, as your not disposing immediately the suppression will remain active until the Garbage Collector comes along to clean up, hence the delay.

You must be logged in to vote
7 replies
@sinatrocious
Comment options

Yes, same. VS prompts me withIDE0063.

@ChrisPulman
Comment options

Okay, I will take a look at this later when I finish work.

@ChrisPulman
Comment options

Okay, the binding is a bool, WhenAnyValue gives change notifications so therefore this is the way it currently operates:

using this code

public MainViewModel(){    var count = 0;    this.WhenAnyValue(o => o.Value).Subscribe(value => Text = value.ToString() + count++);    Test = ReactiveCommand.Create(() =>    {        using var dispose = SuppressChangeNotifications();        Value = true;        count = 0;    });}

Scenario 1 - Suppression When FALSE with a suppressed TRUE change

Unchecked => changes falseChecked => changes trueUnchecked => changes falseSuppressChangeNotifications{Set Value true => no change as suppressedDispose Suppression}Checked => no change due to equal to suppressed valueUnchecked => no change as equal to last changeChecked => changes true

Scenario 2 - Suppression When TRUE with a suppressed TRUE change

Unchecked => changes falseChecked => changes trueSuppressChangeNotifications{Set Value true => no change as suppressedDispose Suppression}Unchecked => changes false as not equal to last changeChecked => changes true

using this code

public MainViewModel(){    var count = 0;    this.WhenAnyValue(o => o.Value).Subscribe(value => Text = value.ToString() + count++);    Test = ReactiveCommand.Create(() =>    {        using var dispose = SuppressChangeNotifications();        Value = false;        count = 0;    });}

Scenario 3 - Suppression When FALSE with a suppressed FALSE change

Unchecked => changes falseChecked => changes trueUnchecked => changes falseSuppressChangeNotifications{Set Value false=> no change as suppressedDispose Suppression}Checked => changes trueUnchecked => changes false

Scenario 4 - Suppression When TRUE with a suppressed FALSE change

Unchecked => changes falseChecked => changes trueSuppressChangeNotifications{Set Value false=> no change as suppressedDispose Suppression}Unchecked => no change due to equal to suppressed valueChecked => no change as equal to last changeUnchecked => changes false
@sinatrocious
Comment options

Hmm.. "no change as equal to last change" happens because the change while suppressed will cause same value to be ignored and not remembered as "last change". That make sense, thanks.

Is it possible to update that "last changed" value while suppressing? My intent is to update value without triggering anyWhenAnyValue().Subscribe(), but any change after suppression should work without problems! I am willing to add some logic where I suppress change, but I'd like to keep subscribers code clean.

As I said earlier, I don't want to introducebool flag to be checked by every subscriber, whenever they need to ignore change made while flag is set:

Show/hide code with bool flag
this.WhenAnyValue(o=>o.Value).Subscribe(value=>{if(!IgnoreValue)// suppressed changes are ignored by subscriberText=value.ToString();});Test=ReactiveCommand.Create(()=>{IgnoreValue=true;// suppress changes by setting flagValue=true;IgnoreValue=false;});
@sinatrocious
Comment options

I've refactored the code with bool flag and it looks not so bad:

Show/hide refactored code
publicclassMainViewModel:ReactiveObject,ISuspendable{[Reactive]publicstring?Text{get;set;}[Reactive]publicboolValue{get;set;}publicReactiveCommand<Unit,Unit>Test{get;}boolISuspendable.IsSuspended{get;set;}publicMainViewModel(){this.WhenAnyValue(o=>o.Value).Subscribe(this, value=>Text=value.ToString());Test=ReactiveCommand.Create(()=>{usingvardispose=this.Suspend();Value=true;});}}publicinterfaceISuspendable{boolIsSuspended{get;set;}}publicsealedclassSuspendableDisposeHelper:IDisposable{readonlyISuspendablesuspendable;publicSuspendableDisposeHelper(ISuspendablesuspendable){this.suspendable=suspendable;suspendable.IsSuspended=true;}publicvoidDispose()=>suspendable.IsSuspended=false;}publicstaticclassSuspendableExtensions{publicstaticIDisposableSuspend(thisISuspendablesuspendable)=>newSuspendableDisposeHelper(suspendable);publicstaticIDisposableSubscribe<T>(thisIObservable<T>source,ISuspendablesuspendable,Action<T>onNext)=>source.Subscribe(o=>{if(!suspendable.IsSuspended)onNext(o);});}

There is one more parameter to pass intoSubscribe method, but otherwise the code looks similar to one withSuppressChangeNotifications.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Q&A
Labels
None yet
3 participants
@sinatrocious@anaisbetts@ChrisPulman

[8]ページ先頭

©2009-2025 Movatter.jp