I'm would like to know the recommended way to bind to ReactiveCommand's IsExecuting
.
The problem is the initial command execution (started at the end of the constructor) is not updating the WPF control using IsLoading
as a binding, although subsequent calls work as expected.
Update 2 Add test binding code
This shows the adorner content when IsLoading
is 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 figured I should be able to do something like:
this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
.ToProperty(this, x => x.IsLoading);
but it gives the compilation error:
The type arguments for 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 inferred from the usage. Try specifying the type arguments explicitly.
I also tried:
this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
.ToProperty<TheViewModel, bool>(this, x => x.IsLoading);
but get the compilation error:
'System.IObservable< System.IObservable< bool >>' does not contain a definition for 'ToProperty' and the best extension method overload '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 listed at the end of my post works for the initial bind by accessing the IsLoading
property and it sounds like that kicks off a subscription. But from further reading it seems I should be using WhenAny
and I can't seem to figure out what has been put in front of my nose:
ToProperty and BindTo - Get initial value without Subscribing
Adding:
this.WhenAnyValue(x => x.LoadCommand.IsExecuting);
also works, but is there a better way?
I was thinking removing the ObservableAsPropertyHelper
as it doesn't seem to be doing much for me and making IsLoading
a normal property like:
private bool _isLoading;
public bool IsLoading
{
get { return _isLoading; }
set { this.RaiseAndSetIfChanged(ref _isLoading, value); }
}
And doing something like the following, but it doesn't compile because it is trying to assign a IObservable< bool>
to a 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();