Browse Source

Allow ExpressionObserver root to be changed.

Steven Kirk 10 years ago
parent
commit
072aa3c96d

+ 23 - 3
src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs

@@ -12,6 +12,7 @@ namespace Perspex.Markup.Binding
     /// </summary>
     public class ExpressionObserver : ObservableBase<ExpressionValue>
     {
+        private object _root;
         private int _count;
         private ExpressionNode _node;
 
@@ -22,7 +23,7 @@ namespace Perspex.Markup.Binding
         /// <param name="expression">The expression.</param>
         public ExpressionObserver(object root, string expression)
         {
-            Root = root;
+            _root = root;
             _node = ExpressionNodeBuilder.Build(expression);
         }
 
@@ -49,9 +50,28 @@ namespace Perspex.Markup.Binding
         }
 
         /// <summary>
-        /// Gets the root object that the expression is being observed on.
+        /// Gets or sets the root object that the expression is being observed on.
         /// </summary>
-        public object Root { get; }
+        public object Root
+        {
+            get
+            {
+                return _root;
+            }
+
+            set
+            {
+                if (_root != value)
+                {
+                    _root = value;
+
+                    if (_count > 0)
+                    {
+                        _node.Target = _root;
+                    }
+                }
+            }
+        }
 
         /// <inheritdoc/>
         protected override IDisposable SubscribeCore(IObserver<ExpressionValue> observer)

+ 27 - 0
tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests_Property.cs

@@ -200,6 +200,33 @@ namespace Perspex.Markup.UnitTests.Binding
             Assert.Throws<ArgumentException>(() => target.SetValue(1.2));
         }
 
+        [Fact]
+        public async void Should_Handle_Null_Root()
+        {
+            var target = new ExpressionObserver(null, "Foo");
+            var result = await target.Take(1);
+
+            Assert.False(result.HasValue);
+        }
+
+        [Fact]
+        public void Can_Replace_Root()
+        {
+            var first = new Class1 { Foo = "foo" };
+            var second = new Class1 { Foo = "bar" };
+            var target = new ExpressionObserver(first, "Foo");
+            var result = new List<object>();
+
+            var sub = target.Subscribe(x => result.Add(x.Value));
+            target.Root = second;
+            target.Root = null;
+
+            Assert.Equal(new[] { "foo", "bar", null }, result);
+
+            Assert.Equal(0, first.SubscriptionCount);
+            Assert.Equal(0, second.SubscriptionCount);
+        }
+
         private interface INext
         {
             int SubscriptionCount { get; }