12 changed files with 485 additions and 192 deletions
@ -0,0 +1,80 @@ |
|||||
|
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Reactive; |
||||
|
using System.Reactive.Linq; |
||||
|
|
||||
|
namespace Perspex.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// An observable which is switched on or off according to an activator observable.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// An <see cref="ActivatedObservable"/> has two inputs: an activator observable a
|
||||
|
/// <see cref="Source"/> observable which produces the activated value. When the activator
|
||||
|
/// produces true, the <see cref="ActivatedObservable"/> will produce the current activated
|
||||
|
/// value. When the activator produces false it will produce
|
||||
|
/// <see cref="PerspexProperty.UnsetValue"/>.
|
||||
|
/// </remarks>
|
||||
|
internal class ActivatedObservable : ObservableBase<object>, IDescription |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The activator.
|
||||
|
/// </summary>
|
||||
|
private readonly IObservable<bool> _activator; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ActivatedObservable"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="activator">The activator.</param>
|
||||
|
/// <param name="source">An observable that produces the activated value.</param>
|
||||
|
/// <param name="description">The binding description.</param>
|
||||
|
public ActivatedObservable( |
||||
|
IObservable<bool> activator, |
||||
|
IObservable<object> source, |
||||
|
string description) |
||||
|
{ |
||||
|
_activator = activator; |
||||
|
Description = description; |
||||
|
Source = source; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a description of the binding.
|
||||
|
/// </summary>
|
||||
|
public string Description |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an observable which produces the <see cref="ActivatedValue"/>.
|
||||
|
/// </summary>
|
||||
|
public IObservable<object> Source |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies the provider that an observer is to receive notifications.
|
||||
|
/// </summary>
|
||||
|
/// <param name="observer">The observer.</param>
|
||||
|
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
||||
|
protected override IDisposable SubscribeCore(IObserver<object> observer) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(observer != null); |
||||
|
|
||||
|
var sourceCompleted = Source.TakeLast(1).Select(_ => Unit.Default); |
||||
|
var activatorCompleted = _activator.TakeLast(1).Select(_ => Unit.Default); |
||||
|
var completed = sourceCompleted.Merge(activatorCompleted); |
||||
|
|
||||
|
return _activator |
||||
|
.CombineLatest(Source, (x, y) => new { Active = x, Value = y }) |
||||
|
.Select(x => x.Active ? x.Value : PerspexProperty.UnsetValue) |
||||
|
.DistinctUntilChanged() |
||||
|
.TakeUntil(completed) |
||||
|
.Subscribe(observer); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,124 @@ |
|||||
|
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Reactive; |
||||
|
using System.Reactive.Linq; |
||||
|
using System.Reactive.Subjects; |
||||
|
|
||||
|
namespace Perspex.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A subject which is switched on or off according to an activator observable.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// An <see cref="ActivatedSubject"/> has two inputs: an activator observable and either an
|
||||
|
/// <see cref="ActivatedValue"/> or a <see cref="Source"/> observable which produces the
|
||||
|
/// activated value. When the activator produces true, the <see cref="ActivatedObservable"/> will
|
||||
|
/// produce the current activated value. When the activator produces false it will produce
|
||||
|
/// <see cref="PerspexProperty.UnsetValue"/>.
|
||||
|
/// </remarks>
|
||||
|
internal class ActivatedSubject : ISubject<object>, IDescription |
||||
|
{ |
||||
|
private IObservable<bool> _activator; |
||||
|
private bool _active; |
||||
|
private object _pushValue; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ActivatedSubject"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="activator">The activator.</param>
|
||||
|
/// <param name="source">An observable that produces the activated value.</param>
|
||||
|
/// <param name="description">The binding description.</param>
|
||||
|
public ActivatedSubject( |
||||
|
IObservable<bool> activator, |
||||
|
ISubject<object> source, |
||||
|
string description) |
||||
|
{ |
||||
|
_activator = activator; |
||||
|
Description = description; |
||||
|
Source = source; |
||||
|
|
||||
|
_activator.Skip(1).Subscribe(ActivatorChanged); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a description of the binding.
|
||||
|
/// </summary>
|
||||
|
public string Description |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the underlying subject.
|
||||
|
/// </summary>
|
||||
|
public ISubject<object> Source |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies all subscribed observers about the end of the sequence.
|
||||
|
/// </summary>
|
||||
|
public void OnCompleted() |
||||
|
{ |
||||
|
if (_active) |
||||
|
{ |
||||
|
Source.OnCompleted(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies all subscribed observers with the exception.
|
||||
|
/// </summary>
|
||||
|
/// <param name="error">The exception to send to all subscribed observers.</param>
|
||||
|
/// <exception cref="ArgumentNullException"><paramref name="error"/> is null.</exception>
|
||||
|
public void OnError(Exception error) |
||||
|
{ |
||||
|
if (_active) |
||||
|
{ |
||||
|
Source.OnError(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies all subscribed observers with the value.
|
||||
|
/// </summary>
|
||||
|
/// <param name="value">The value to send to all subscribed observers.</param>
|
||||
|
public void OnNext(object value) |
||||
|
{ |
||||
|
_pushValue = value; |
||||
|
|
||||
|
if (_active) |
||||
|
{ |
||||
|
Source.OnNext(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies the provider that an observer is to receive notifications.
|
||||
|
/// </summary>
|
||||
|
/// <param name="observer">The observer.</param>
|
||||
|
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
||||
|
public IDisposable Subscribe(IObserver<object> observer) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(observer != null); |
||||
|
|
||||
|
var completed = _activator.TakeLast(1).Select(_ => Unit.Default); |
||||
|
|
||||
|
return _activator |
||||
|
.CombineLatest(Source, (x, y) => new { Active = x, Value = y }) |
||||
|
.Select(x => x.Active ? x.Value : PerspexProperty.UnsetValue) |
||||
|
.DistinctUntilChanged() |
||||
|
.TakeUntil(completed) |
||||
|
.Subscribe(observer); |
||||
|
} |
||||
|
|
||||
|
private void ActivatorChanged(bool active) |
||||
|
{ |
||||
|
_active = active; |
||||
|
Source.OnNext(active ? _pushValue : PerspexProperty.UnsetValue); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,72 @@ |
|||||
|
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Reactive; |
||||
|
using System.Reactive.Linq; |
||||
|
|
||||
|
namespace Perspex.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// An value which is switched on or off according to an activator observable.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// An <see cref="ActivatedValue"/> has two inputs: an activator observable and an
|
||||
|
/// <see cref="Value"/>. When the activator produces true, the
|
||||
|
/// <see cref="ActivatedValue"/> will produce the current value. When the activator
|
||||
|
/// produces false it will produce <see cref="PerspexProperty.UnsetValue"/>.
|
||||
|
/// </remarks>
|
||||
|
internal class ActivatedValue : ObservableBase<object>, IDescription |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The activator.
|
||||
|
/// </summary>
|
||||
|
private readonly IObservable<bool> _activator; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ActivatedObservable"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="activator">The activator.</param>
|
||||
|
/// <param name="value">The activated value.</param>
|
||||
|
/// <param name="description">The binding description.</param>
|
||||
|
public ActivatedValue( |
||||
|
IObservable<bool> activator, |
||||
|
object value, |
||||
|
string description) |
||||
|
{ |
||||
|
_activator = activator; |
||||
|
Value = value; |
||||
|
Description = description; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the activated value.
|
||||
|
/// </summary>
|
||||
|
public object Value |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a description of the binding.
|
||||
|
/// </summary>
|
||||
|
public string Description |
||||
|
{ |
||||
|
get; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies the provider that an observer is to receive notifications.
|
||||
|
/// </summary>
|
||||
|
/// <param name="observer">The observer.</param>
|
||||
|
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
||||
|
protected override IDisposable SubscribeCore(IObserver<object> observer) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(observer != null); |
||||
|
|
||||
|
return _activator |
||||
|
.Select(active => active ? Value : PerspexProperty.UnsetValue) |
||||
|
.Subscribe(observer); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,107 +0,0 @@ |
|||||
// Copyright (c) The Perspex Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Reactive; |
|
||||
using System.Reactive.Linq; |
|
||||
|
|
||||
namespace Perspex.Styling |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Provides an observable for a style.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// A <see cref="StyleBinding"/> has two inputs: an activator observable and either an
|
|
||||
/// <see cref="ActivatedValue"/> or a <see cref="Source"/> observable which produces the
|
|
||||
/// activated value. When the activator produces true, the <see cref="StyleBinding"/> will
|
|
||||
/// produce the current activated value. When the activator produces false it will produce
|
|
||||
/// <see cref="PerspexProperty.UnsetValue"/>.
|
|
||||
/// </remarks>
|
|
||||
internal class StyleBinding : ObservableBase<object>, IDescription |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The activator.
|
|
||||
/// </summary>
|
|
||||
private readonly IObservable<bool> _activator; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="StyleBinding"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="activator">The activator.</param>
|
|
||||
/// <param name="activatedValue">The activated value.</param>
|
|
||||
/// <param name="description">The binding description.</param>
|
|
||||
public StyleBinding( |
|
||||
IObservable<bool> activator, |
|
||||
object activatedValue, |
|
||||
string description) |
|
||||
{ |
|
||||
_activator = activator; |
|
||||
ActivatedValue = activatedValue; |
|
||||
Description = description; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="StyleBinding"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="activator">The activator.</param>
|
|
||||
/// <param name="source">An observable that produces the activated value.</param>
|
|
||||
/// <param name="description">The binding description.</param>
|
|
||||
public StyleBinding( |
|
||||
IObservable<bool> activator, |
|
||||
IObservable<object> source, |
|
||||
string description) |
|
||||
{ |
|
||||
_activator = activator; |
|
||||
Description = description; |
|
||||
Source = source; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the activated value.
|
|
||||
/// </summary>
|
|
||||
public object ActivatedValue |
|
||||
{ |
|
||||
get; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a description of the binding.
|
|
||||
/// </summary>
|
|
||||
public string Description |
|
||||
{ |
|
||||
get; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets an observable which produces the <see cref="ActivatedValue"/>.
|
|
||||
/// </summary>
|
|
||||
public IObservable<object> Source |
|
||||
{ |
|
||||
get; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Notifies the provider that an observer is to receive notifications.
|
|
||||
/// </summary>
|
|
||||
/// <param name="observer">The observer.</param>
|
|
||||
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
|
||||
protected override IDisposable SubscribeCore(IObserver<object> observer) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(observer != null); |
|
||||
|
|
||||
if (Source == null) |
|
||||
{ |
|
||||
return _activator |
|
||||
.Select(active => active ? ActivatedValue : PerspexProperty.UnsetValue) |
|
||||
.Subscribe(observer); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
return _activator |
|
||||
.CombineLatest(Source, (x, y) => new { Active = x, Value = y }) |
|
||||
.Select(x => x.Active ? x.Value : PerspexProperty.UnsetValue) |
|
||||
.Subscribe(observer); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,70 @@ |
|||||
|
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reactive.Linq; |
||||
|
using System.Reactive.Subjects; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Perspex.Styling.UnitTests |
||||
|
{ |
||||
|
public class ActivatedObservableTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Should_Produce_Correct_Values() |
||||
|
{ |
||||
|
var activator = new BehaviorSubject<bool>(false); |
||||
|
var source = new BehaviorSubject<object>(1); |
||||
|
var target = new ActivatedObservable(activator, source, string.Empty); |
||||
|
var result = new List<object>(); |
||||
|
|
||||
|
target.Subscribe(x => result.Add(x)); |
||||
|
|
||||
|
activator.OnNext(true); |
||||
|
source.OnNext(2); |
||||
|
activator.OnNext(false); |
||||
|
source.OnNext(3); |
||||
|
activator.OnNext(true); |
||||
|
|
||||
|
Assert.Equal( |
||||
|
new[] |
||||
|
{ |
||||
|
PerspexProperty.UnsetValue, |
||||
|
1, |
||||
|
2, |
||||
|
PerspexProperty.UnsetValue, |
||||
|
3, |
||||
|
}, |
||||
|
result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Complete_When_Source_Completes() |
||||
|
{ |
||||
|
var activator = new BehaviorSubject<bool>(false); |
||||
|
var source = new BehaviorSubject<object>(1); |
||||
|
var target = new ActivatedObservable(activator, source, string.Empty); |
||||
|
var completed = false; |
||||
|
|
||||
|
target.Subscribe(_ => { }, () => completed = true); |
||||
|
source.OnCompleted(); |
||||
|
|
||||
|
Assert.True(completed); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Complete_When_Activator_Completes() |
||||
|
{ |
||||
|
var activator = new BehaviorSubject<bool>(false); |
||||
|
var source = new BehaviorSubject<object>(1); |
||||
|
var target = new ActivatedObservable(activator, source, string.Empty); |
||||
|
var completed = false; |
||||
|
|
||||
|
target.Subscribe(_ => { }, () => completed = true); |
||||
|
activator.OnCompleted(); |
||||
|
|
||||
|
Assert.True(completed); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System.Reactive.Subjects; |
||||
|
using Perspex.Data; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Perspex.Styling.UnitTests |
||||
|
{ |
||||
|
public class ActivatedSubjectTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Should_Set_Values() |
||||
|
{ |
||||
|
var data = new Class1 { Foo = "foo" }; |
||||
|
var activator = new BehaviorSubject<bool>(false); |
||||
|
var source = data.GetSubject( |
||||
|
(PerspexProperty)Class1.FooProperty, |
||||
|
BindingPriority.LocalValue); |
||||
|
var target = new ActivatedSubject(activator, source, string.Empty); |
||||
|
|
||||
|
target.OnNext("bar"); |
||||
|
Assert.Equal("foo", data.Foo); |
||||
|
activator.OnNext(true); |
||||
|
target.OnNext("baz"); |
||||
|
Assert.Equal("baz", data.Foo); |
||||
|
activator.OnNext(false); |
||||
|
Assert.Equal("foo", data.Foo); |
||||
|
target.OnNext("bax"); |
||||
|
activator.OnNext(true); |
||||
|
Assert.Equal("bax", data.Foo); |
||||
|
} |
||||
|
|
||||
|
private class Class1 : PerspexObject |
||||
|
{ |
||||
|
public static readonly PerspexProperty<string> FooProperty = |
||||
|
PerspexProperty.Register<Class1, string>("Foo", "foodefault"); |
||||
|
|
||||
|
public string Foo |
||||
|
{ |
||||
|
get { return GetValue(FooProperty); } |
||||
|
set { SetValue(FooProperty, value); } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reactive.Linq; |
||||
|
using System.Reactive.Subjects; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Perspex.Styling.UnitTests |
||||
|
{ |
||||
|
public class ActivatedValueTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Should_Produce_Correct_Values() |
||||
|
{ |
||||
|
var activator = new BehaviorSubject<bool>(false); |
||||
|
var target = new ActivatedValue(activator, 1, string.Empty); |
||||
|
var result = new List<object>(); |
||||
|
|
||||
|
target.Subscribe(x => result.Add(x)); |
||||
|
|
||||
|
activator.OnNext(true); |
||||
|
activator.OnNext(false); |
||||
|
|
||||
|
Assert.Equal(new[] { PerspexProperty.UnsetValue, 1, PerspexProperty.UnsetValue }, result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Complete_When_Activator_Completes() |
||||
|
{ |
||||
|
var activator = new BehaviorSubject<bool>(false); |
||||
|
var target = new ActivatedValue(activator, 1, string.Empty); |
||||
|
var completed = false; |
||||
|
|
||||
|
target.Subscribe(_ => { }, () => completed = true); |
||||
|
activator.OnCompleted(); |
||||
|
|
||||
|
Assert.True(completed); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,79 +0,0 @@ |
|||||
// Copyright (c) The Perspex Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Reactive.Linq; |
|
||||
using System.Reactive.Subjects; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Perspex.Styling.UnitTests |
|
||||
{ |
|
||||
public class StyleBindingTests |
|
||||
{ |
|
||||
[Fact] |
|
||||
public async void Should_Produce_UnsetValue_On_Activator_False() |
|
||||
{ |
|
||||
var activator = new BehaviorSubject<bool>(false); |
|
||||
var target = new StyleBinding(activator, 1, string.Empty); |
|
||||
var result = await target.Take(1); |
|
||||
|
|
||||
Assert.Equal(PerspexProperty.UnsetValue, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public async void Should_Produce_Value_On_Activator_True() |
|
||||
{ |
|
||||
var activator = new BehaviorSubject<bool>(true); |
|
||||
var target = new StyleBinding(activator, 1, string.Empty); |
|
||||
var result = await target.Take(1); |
|
||||
|
|
||||
Assert.Equal(1, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_Change_Value_On_Activator_Change() |
|
||||
{ |
|
||||
var activator = new BehaviorSubject<bool>(false); |
|
||||
var target = new StyleBinding(activator, 1, string.Empty); |
|
||||
var result = new List<object>(); |
|
||||
|
|
||||
target.Subscribe(x => result.Add(x)); |
|
||||
|
|
||||
activator.OnNext(true); |
|
||||
activator.OnNext(false); |
|
||||
|
|
||||
Assert.Equal(new[] { PerspexProperty.UnsetValue, 1, PerspexProperty.UnsetValue }, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_Change_Value_With_Source_Observable() |
|
||||
{ |
|
||||
var activator = new BehaviorSubject<bool>(false); |
|
||||
var source = new BehaviorSubject<object>(1); |
|
||||
var target = new StyleBinding(activator, source, string.Empty); |
|
||||
var result = new List<object>(); |
|
||||
|
|
||||
target.Subscribe(x => result.Add(x)); |
|
||||
|
|
||||
activator.OnNext(true); |
|
||||
source.OnNext(2); |
|
||||
activator.OnNext(false); |
|
||||
|
|
||||
Assert.Equal(new[] { PerspexProperty.UnsetValue, 1, 2, PerspexProperty.UnsetValue }, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_Complete_When_Activator_Completes() |
|
||||
{ |
|
||||
var activator = new BehaviorSubject<bool>(false); |
|
||||
var target = new StyleBinding(activator, 1, string.Empty); |
|
||||
var completed = false; |
|
||||
|
|
||||
target.Subscribe(_ => { }, () => completed = true); |
|
||||
activator.OnCompleted(); |
|
||||
|
|
||||
Assert.True(completed); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue