From da8267ade75006766cbb97438b2ce8ad0584512b Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 24 Oct 2017 12:00:17 -0500 Subject: [PATCH] Fix last binding test. Two-way bindings via the indexer binding should not cause a PriorityBindingEntry to be created in the target. So instead use SetValue + GetObservable (similar to our higher level implementations in Avalonia.Markup). --- src/Avalonia.Base/AvaloniaObject.cs | 23 +-------- src/Avalonia.Base/AvaloniaObjectExtensions.cs | 24 ++------- .../Reactive/AnonymousSubject`1.cs | 16 ------ .../Reactive/AnonymousSubject`2.cs | 49 ------------------- src/Avalonia.Base/Utilities/DelayedSetter.cs | 26 +++++++++- .../AvaloniaObjectTests_Binding.cs | 1 + 6 files changed, 31 insertions(+), 108 deletions(-) delete mode 100644 src/Avalonia.Base/Reactive/AnonymousSubject`1.cs delete mode 100644 src/Avalonia.Base/Reactive/AnonymousSubject`2.cs diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index b5956d681a..3f53a3735c 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -590,28 +590,7 @@ namespace Avalonia } protected void SetAndRaise(AvaloniaProperty property, Action> setterCallback, T value, Action delayedSet) - { - Contract.Requires(setterCallback != null); - Contract.Requires(delayedSet != null); - if (!directDelayedSetter.IsNotifying(property)) - { - setterCallback(value, notification => - { - using (directDelayedSetter.MarkNotifying(property)) - { - notification(); - } - }); - if (directDelayedSetter.HasPendingSet(property)) - { - delayedSet((T)directDelayedSetter.GetFirstPendingSet(property)); - } - } - else - { - directDelayedSetter.AddPendingSet(property, value); - } - } + => directDelayedSetter.SetAndNotify(property, (val, notify) => setterCallback((T)val, notify), value, val => delayedSet((T)val)); /// /// Tries to cast a value to a type, taking into account that the value may be a diff --git a/src/Avalonia.Base/AvaloniaObjectExtensions.cs b/src/Avalonia.Base/AvaloniaObjectExtensions.cs index 685bf83a75..7967852bfa 100644 --- a/src/Avalonia.Base/AvaloniaObjectExtensions.cs +++ b/src/Avalonia.Base/AvaloniaObjectExtensions.cs @@ -138,17 +138,9 @@ namespace Avalonia AvaloniaProperty property, BindingPriority priority = BindingPriority.LocalValue) { - // TODO: Subject.Create is not yet in stable Rx : once it is, remove the - // AnonymousSubject classes and use Subject.Create. - var output = new Subject(); - var result = new AnonymousSubject( - Observer.Create( - x => output.OnNext(x), - e => output.OnError(e), - () => output.OnCompleted()), + return Subject.Create( + Observer.Create(x => o.SetValue(property, x, priority)), o.GetObservable(property)); - o.Bind(property, output, priority); - return result; } /// @@ -169,17 +161,9 @@ namespace Avalonia AvaloniaProperty property, BindingPriority priority = BindingPriority.LocalValue) { - // TODO: Subject.Create is not yet in stable Rx : once it is, remove the - // AnonymousSubject classes from this file and use Subject.Create. - var output = new Subject(); - var result = new AnonymousSubject( - Observer.Create( - x => output.OnNext(x), - e => output.OnError(e), - () => output.OnCompleted()), + return Subject.Create( + Observer.Create(x => o.SetValue(property, x, priority)), o.GetObservable(property)); - o.Bind(property, output, priority); - return result; } /// diff --git a/src/Avalonia.Base/Reactive/AnonymousSubject`1.cs b/src/Avalonia.Base/Reactive/AnonymousSubject`1.cs deleted file mode 100644 index c7bed15ecb..0000000000 --- a/src/Avalonia.Base/Reactive/AnonymousSubject`1.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) The Avalonia 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.Subjects; - -namespace Avalonia.Reactive -{ - public class AnonymousSubject : AnonymousSubject, ISubject - { - public AnonymousSubject(IObserver observer, IObservable observable) - : base(observer, observable) - { - } - } -} diff --git a/src/Avalonia.Base/Reactive/AnonymousSubject`2.cs b/src/Avalonia.Base/Reactive/AnonymousSubject`2.cs deleted file mode 100644 index 18551d564e..0000000000 --- a/src/Avalonia.Base/Reactive/AnonymousSubject`2.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) The Avalonia 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.Subjects; - -namespace Avalonia.Reactive -{ - public class AnonymousSubject : ISubject - { - private readonly IObserver _observer; - private readonly IObservable _observable; - - public AnonymousSubject(IObserver observer, IObservable observable) - { - _observer = observer; - _observable = observable; - } - - public void OnCompleted() - { - _observer.OnCompleted(); - } - - public void OnError(Exception error) - { - if (error == null) - throw new ArgumentNullException("error"); - - _observer.OnError(error); - } - - public void OnNext(T value) - { - _observer.OnNext(value); - } - - public IDisposable Subscribe(IObserver observer) - { - if (observer == null) - throw new ArgumentNullException("observer"); - - // - // [OK] Use of unsafe Subscribe: non-pretentious wrapping of an observable sequence. - // - return _observable.Subscribe/*Unsafe*/(observer); - } - } -} diff --git a/src/Avalonia.Base/Utilities/DelayedSetter.cs b/src/Avalonia.Base/Utilities/DelayedSetter.cs index c8c9c87d95..3abffbdd3d 100644 --- a/src/Avalonia.Base/Utilities/DelayedSetter.cs +++ b/src/Avalonia.Base/Utilities/DelayedSetter.cs @@ -5,7 +5,7 @@ using System.Text; namespace Avalonia.Utilities { - public class DelayedSetter + class DelayedSetter { private class SettingStatus { @@ -57,5 +57,29 @@ namespace Avalonia.Utilities { return setRecords[property].PendingValues.Dequeue(); } + + public void SetAndNotify(T property, Action> setterCallback, TValue value, Action delayedSet) + { + Contract.Requires(setterCallback != null); + Contract.Requires(delayedSet != null); + if (!IsNotifying(property)) + { + setterCallback(value, notification => + { + using (MarkNotifying(property)) + { + notification(); + } + }); + if (HasPendingSet(property)) + { + delayedSet(GetFirstPendingSet(property)); + } + } + else + { + AddPendingSet(property, value); + } + } } } diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs index b266b44cba..211c7c985e 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs @@ -14,6 +14,7 @@ using Avalonia.Markup.Xaml.Data; using Avalonia.Platform; using Avalonia.Threading; using Avalonia.UnitTests; +using Avalonia.Diagnostics; using Microsoft.Reactive.Testing; using Moq; using Xunit;