Linking to ReactiveCommand.IsExecuting

I would like to know the recommended way to bind to ReactiveCommand IsExecuting .

The problem is that the initial execution of the command (started at the end of the constructor) does not update the WPF control using IsLoading as a binding, although subsequent calls work as expected.

Update 2 Add Code Binding Code

It shows adorner content when IsLoading true

 <ac:AdornedControl IsAdornerVisible="{Binding IsLoading}"> <ac:AdornedControl.AdornerContent> <controls1:LoadingAdornerContent/> </ac:AdornedControl.AdornerContent> <fluent:ComboBox ItemsSource="{Binding Content, Mode=OneWay}" DisplayMemberPath="Name" SelectedValuePath="ContentId" SelectedValue="{Binding SelectedContentId}" IsSynchronizedWithCurrentItem="True" /> </ac:AdornedControl> 

Update

I found this: https://github.com/reactiveui/rxui-design-guidelines

and realized that I should do something like:

 this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting) .ToProperty(this, x => x.IsLoading); 

but it gives a compilation error:

Type arguments for the method "ReactiveUI.OAPHCreationHelperMixin.ToProperty <TObj, TRet> (System.IObservable <TRet>, TObj, System.Linq.Expressions.Expression <System.Func <TObj, TRet →, TRet, System.Reactive.Concurrency. IScheduler) 'cannot be deduced from Application. Try to explicitly specify type arguments.

I also tried:

 this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting) .ToProperty<TheViewModel, bool>(this, x => x.IsLoading); 

but get a compilation error:

'System.IObservable <System.IObservable <bool →' does not contain the definition of “ToProperty” and the best overload of the extension method is “ReactiveUI.OAPHCreationHelperMixin.ToProperty <TObj, TRet> (System.IObservable <TRet>, TObj, System.Linq.Expressions. Expression <System.Func <TObj, TRet →, TRet, System.Reactive.Concurrency.IScheduler) 'has some invalid arguments

and

Instance argument: cannot convert from 'System.IObservable>' to 'System.IObservable'

Original below

The code at the end of my post works for the initial binding, accessing the IsLoading property, and it looks like this is starting a subscription. But from further reading it seems that I should use WhenAny , and I can’t understand what was put in front of my nose:

ToProperty and BindTo - get the initial value without a subscription

Addendum:

 this.WhenAnyValue(x => x.LoadCommand.IsExecuting); 

also works, but is there a better way?

I was thinking about removing the ObservableAsPropertyHelper , as it does not seem to do much for me and makes IsLoading normal property like:

 private bool _isLoading; public bool IsLoading { get { return _isLoading; } set { this.RaiseAndSetIfChanged(ref _isLoading, value); } } 

And we will do something like the following, but it does not compile because it is trying to assign an IObservable< bool> to bool:

 this.WhenAnyValue(x => x.LoadCommand.IsExecuting) .Subscribe(x => IsLoading = x); 

Current code:

 private readonly ObservableAsPropertyHelper<bool> _isLoading; public bool IsLoading { get { return _isLoading.Value; } } LoadCommand = ReactiveCommand.CreateAsyncTask(async _ => { //go do command stuff like fetch data from a database } LoadCommand.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading); //works if I have this line var startSubscription = IsLoading; LoadCommand.ExecuteAsyncTask(); 
+6
source share
2 answers

and realized that I should do something like:

You have the right idea, but the syntax is a bit off, try:

 this.LoadCommand.IsExecuting .ToProperty(this, x => x.IsLoading, out _isLoading); 

If you were to do this with objects that could change (i.e. you got a long expression), the special WhenAnyObservable method is WhenAnyObservable , which you use instead of WhenAnyValue :

 this.WhenAnyObservable(x => x.SomeObjectThatMightBeReplaced.IsExecuting) .ToProperty(this, x => x.IsLoading, out _isLoading); 
+6
source

I have come across this before, and I think you are experiencing a lie here .

ToProperty / OAPH changes

  • ObservableAsPropertyHelper is no longer an IObservable, use WhenAny to observe it.

  • ObservableAsPropertyHelper is now lazy. Subscribe to the source only when the value is read the first time. This greatly improves performance and memory usage, but at the cost of some “Why is my test work?” confusion. If you find that your ToProperty is "not working," maybe that’s why.

This is lazy, so you have to subscribe to it (i.e. request the value from the property when using OAPH) for it to work. This is why you notice that your var startSubscription = IsLoading; "fixes" the problem.

Knowing this made it easier for me to determine whether it was even a problem, or something to keep in mind during my unit tests, knowing that in my application these properties will be related and therefore signed, this is a moot point in practice. You know, all "a tree falling in a forest where no one hears."

I think you should stick with the ToProperty that you have, and that seems like the IMHO path.

+3
source

Source: https://habr.com/ru/post/974602/


All Articles