Permalink
Browse files

User provided initial state for ReactiveAsyncCommands

ReactiveAsyncCommands when driven by an IObservable defaults initially
to reporting CanExecute as true before any events pass through the
canExecute observable.  This change keeps that default behavior, but
allows the user to change this default to false if appropriate.
  • Loading branch information...
1 parent d8ab384 commit 07b99f705b0cfb0a01ebb9c42ea9c7ac61218458 @sillyotter sillyotter committed Jan 10, 2013
Showing with 61 additions and 4 deletions.
  1. +56 −0 ReactiveUI.Tests/ReactiveCommandTest.cs
  2. +5 −4 ReactiveUI.Xaml/ReactiveAsyncCommand.cs
@@ -6,6 +6,7 @@
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;
+using System.Threading.Tasks;
using Microsoft.Reactive.Testing;
using ReactiveUI.Testing;
@@ -455,5 +456,60 @@ public void CanExecuteShouldChangeOnInflightOp()
Assert.False(latestCanExecute);
});
}
+
+
+
+ private Task<bool> DummyTestFunction()
+ {
+ return Task.Factory.StartNew(() => true);
+ }
+
+ [Fact]
+ public void ReactiveAsyncCommandInitialConditionDefaultBehavior()
+ {
+ (new TestScheduler()).With(sched => {
+ var canExecute = sched.CreateHotObservable(
+ sched.OnNextAt(0, false),
+ sched.OnNextAt(250, true)
+ );
+
+ var fixture = new ReactiveAsyncCommand(canExecute);
+
+ fixture.RegisterAsyncTask(_ => DummyTestFunction());
+
+ Assert.True(fixture.CanExecute(null));
+
+ sched.AdvanceToMs(10);
+ Assert.False(fixture.CanExecute(null));
+
+ sched.AdvanceToMs(255);
+ Assert.True(fixture.CanExecute(null));
+ });
+ }
+
+
+ [Fact]
+ public void ReactiveAsyncCommandInitialConditionNewBehavior()
+ {
+ (new TestScheduler()).With(sched =>
+ {
+ var canExecute = sched.CreateHotObservable(
+ sched.OnNextAt(0, false),
+ sched.OnNextAt(250, true)
+ );
+
+ var fixture = new ReactiveAsyncCommand(canExecute, initialCondition:false);
+
+ fixture.RegisterAsyncTask(_ => DummyTestFunction());
+
+ Assert.False(fixture.CanExecute(null));
+
+ sched.AdvanceToMs(10);
+ Assert.False(fixture.CanExecute(null));
+
+ sched.AdvanceToMs(255);
+ Assert.True(fixture.CanExecute(null));
+ });
+ }
}
}
@@ -34,9 +34,10 @@ public class ReactiveAsyncCommand : IReactiveAsyncCommand, IDisposable, IEnableL
public ReactiveAsyncCommand(
IObservable<bool> canExecute = null,
int maximumConcurrent = 1,
- IScheduler scheduler = null)
+ IScheduler scheduler = null,
+ bool initialCondition = true)
{
- commonCtor(maximumConcurrent, scheduler, canExecute);
+ commonCtor(maximumConcurrent, scheduler, canExecute, initialCondition);
}
protected ReactiveAsyncCommand(
@@ -75,7 +76,7 @@ public class ReactiveAsyncCommand : IReactiveAsyncCommand, IDisposable, IEnableL
return ret;
}
- void commonCtor(int maximumConcurrent, IScheduler scheduler, IObservable<bool> canExecute = null)
+ void commonCtor(int maximumConcurrent, IScheduler scheduler, IObservable<bool> canExecute = null, bool initialCondition = true)
{
_normalSched = scheduler ?? RxApp.DeferredScheduler;
_canExecuteSubject = new ScheduledSubject<bool>(_normalSched);
@@ -96,7 +97,7 @@ void commonCtor(int maximumConcurrent, IScheduler scheduler, IObservable<bool> c
return ret;
}).Multicast(new BehaviorSubject<int>(0)).PermaRef().ObserveOn(RxApp.DeferredScheduler);
- bool startCE = (_canExecuteExplicitFunc != null ? _canExecuteExplicitFunc(null) : true);
+ bool startCE = (_canExecuteExplicitFunc != null ? _canExecuteExplicitFunc(null) : initialCondition);
CanExecuteObservable = Observable.CombineLatest(
_canExecuteSubject.StartWith(startCE), ItemsInflight.Select(x => x < maximumConcurrent).StartWith(true),

0 comments on commit 07b99f7

Please sign in to comment.