瀏覽代碼

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).

Jeremy Koritzinsky 8 年之前
父節點
當前提交
da8267ade7

+ 1 - 22
src/Avalonia.Base/AvaloniaObject.cs

@@ -590,28 +590,7 @@ namespace Avalonia
         }
         }
 
 
         protected void SetAndRaise<T>(AvaloniaProperty<T> property, Action<T, Action<Action>> setterCallback, T value, Action<T> delayedSet)
         protected void SetAndRaise<T>(AvaloniaProperty<T> property, Action<T, Action<Action>> setterCallback, T value, Action<T> delayedSet)
-        {
-            Contract.Requires<ArgumentNullException>(setterCallback != null);
-            Contract.Requires<ArgumentNullException>(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));
 
 
         /// <summary>
         /// <summary>
         /// Tries to cast a value to a type, taking into account that the value may be a
         /// Tries to cast a value to a type, taking into account that the value may be a

+ 4 - 20
src/Avalonia.Base/AvaloniaObjectExtensions.cs

@@ -138,17 +138,9 @@ namespace Avalonia
             AvaloniaProperty property,
             AvaloniaProperty property,
             BindingPriority priority = BindingPriority.LocalValue)
             BindingPriority priority = BindingPriority.LocalValue)
         {
         {
-            // TODO: Subject.Create<T> is not yet in stable Rx : once it is, remove the 
-            // AnonymousSubject classes and use Subject.Create<T>.
-            var output = new Subject<object>();
-            var result = new AnonymousSubject<object>(
-                Observer.Create<object>(
-                    x => output.OnNext(x),
-                    e => output.OnError(e),
-                    () => output.OnCompleted()),
+            return Subject.Create<object>(
+                Observer.Create<object>(x => o.SetValue(property, x, priority)),
                 o.GetObservable(property));
                 o.GetObservable(property));
-            o.Bind(property, output, priority);
-            return result;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -169,17 +161,9 @@ namespace Avalonia
             AvaloniaProperty<T> property,
             AvaloniaProperty<T> property,
             BindingPriority priority = BindingPriority.LocalValue)
             BindingPriority priority = BindingPriority.LocalValue)
         {
         {
-            // TODO: Subject.Create<T> is not yet in stable Rx : once it is, remove the 
-            // AnonymousSubject classes from this file and use Subject.Create<T>.
-            var output = new Subject<T>();
-            var result = new AnonymousSubject<T>(
-                Observer.Create<T>(
-                    x => output.OnNext(x),
-                    e => output.OnError(e),
-                    () => output.OnCompleted()),
+            return Subject.Create<T>(
+                Observer.Create<T>(x => o.SetValue(property, x, priority)),
                 o.GetObservable(property));
                 o.GetObservable(property));
-            o.Bind(property, output, priority);
-            return result;
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 0 - 16
src/Avalonia.Base/Reactive/AnonymousSubject`1.cs

@@ -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<T> : AnonymousSubject<T, T>, ISubject<T>
-    {
-        public AnonymousSubject(IObserver<T> observer, IObservable<T> observable)
-            : base(observer, observable)
-        {
-        }
-    }
-}

+ 0 - 49
src/Avalonia.Base/Reactive/AnonymousSubject`2.cs

@@ -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<T, U> : ISubject<T, U>
-    {
-        private readonly IObserver<T> _observer;
-        private readonly IObservable<U> _observable;
-
-        public AnonymousSubject(IObserver<T> observer, IObservable<U> 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<U> 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);
-        }
-    }
-}

+ 25 - 1
src/Avalonia.Base/Utilities/DelayedSetter.cs

@@ -5,7 +5,7 @@ using System.Text;
 
 
 namespace Avalonia.Utilities
 namespace Avalonia.Utilities
 {
 {
-    public class DelayedSetter<T, TValue>
+    class DelayedSetter<T, TValue>
     {
     {
         private class SettingStatus
         private class SettingStatus
         {
         {
@@ -57,5 +57,29 @@ namespace Avalonia.Utilities
         {
         {
             return setRecords[property].PendingValues.Dequeue();
             return setRecords[property].PendingValues.Dequeue();
         }
         }
+
+        public void SetAndNotify(T property, Action<TValue, Action<Action>> setterCallback, TValue value, Action<TValue> delayedSet)
+        {
+            Contract.Requires<ArgumentNullException>(setterCallback != null);
+            Contract.Requires<ArgumentNullException>(delayedSet != null);
+            if (!IsNotifying(property))
+            {
+                setterCallback(value, notification =>
+                {
+                    using (MarkNotifying(property))
+                    {
+                        notification();
+                    }
+                });
+                if (HasPendingSet(property))
+                {
+                    delayedSet(GetFirstPendingSet(property));
+                }
+            }
+            else
+            {
+                AddPendingSet(property, value);
+            }
+        }
     }
     }
 }
 }

+ 1 - 0
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs

@@ -14,6 +14,7 @@ using Avalonia.Markup.Xaml.Data;
 using Avalonia.Platform;
 using Avalonia.Platform;
 using Avalonia.Threading;
 using Avalonia.Threading;
 using Avalonia.UnitTests;
 using Avalonia.UnitTests;
+using Avalonia.Diagnostics;
 using Microsoft.Reactive.Testing;
 using Microsoft.Reactive.Testing;
 using Moq;
 using Moq;
 using Xunit;
 using Xunit;