Browse Source

Implement OneTime binding.

Steven Kirk 10 years ago
parent
commit
1064fbd186

+ 4 - 4
samples/BindingTest/MainWindow.paml

@@ -1,9 +1,9 @@
 <Window xmlns="https://github.com/perspex">
   <StackPanel Margin="18" Gap="4">
     <TextBlock Text="{Binding SimpleBinding}"/>
-    <TextBox Watermark="Two Way" Text="{Binding SimpleBinding}"/>
-    <TextBox Watermark="One Way" Text="{Binding SimpleBinding, Mode=OneWay}"/>
-    <TextBox Watermark="One Time" Text="{Binding SimpleBinding, Mode=OneTime}"/>
-    <TextBox Watermark="One Way To Source" Text="{Binding SimpleBinding, Mode=OneWayToSource}"/>
+    <TextBox Watermark="Two Way" UseFloatingWatermark="True" Text="{Binding SimpleBinding}"/>
+    <TextBox Watermark="One Way" UseFloatingWatermark="True" Text="{Binding SimpleBinding, Mode=OneWay}"/>
+    <TextBox Watermark="One Time" UseFloatingWatermark="True" Text="{Binding SimpleBinding, Mode=OneTime}"/>
+    <TextBox Watermark="One Way To Source" UseFloatingWatermark="True" Text="{Binding SimpleBinding, Mode=OneWayToSource}"/>
   </StackPanel>
 </Window>

+ 10 - 17
src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs

@@ -5,6 +5,7 @@ using System;
 using System.Reactive.Linq;
 using System.Reactive.Subjects;
 using OmniXaml.TypeConversion;
+using Perspex.Controls;
 using Perspex.Markup.Binding;
 
 namespace Perspex.Markup.Xaml.Binding
@@ -26,8 +27,6 @@ namespace Perspex.Markup.Xaml.Binding
 
         public PerspexProperty TargetProperty { get; set; }
 
-        public object Source { get; set; }
-
         public string SourcePropertyPath { get; set; }
 
         public BindingMode BindingMode { get; set; }
@@ -39,20 +38,10 @@ namespace Perspex.Markup.Xaml.Binding
 
         public ExpressionObserver CreateExpressionObserver()
         {
-            var path = SourcePropertyPath;
-            var source = Source;
-
-            if (source == null)
-            {
-                if (!string.IsNullOrWhiteSpace(path))
-                {
-                    path = "DataContext." + path;
-                }
-
-                source = Target;
-            }
-
-            return new ExpressionObserver(source, path);
+            var result = new ExpressionObserver(null, SourcePropertyPath);
+            var dataContext = Target.GetObservable(Control.DataContextProperty);
+            dataContext.Subscribe(x => result.Root = x);
+            return result;
         }
 
         internal void Bind(ISubject<object> subject)
@@ -70,7 +59,11 @@ namespace Perspex.Markup.Xaml.Binding
                     Target.BindTwoWay(TargetProperty, subject);
                     break;
                 case BindingMode.OneTime:
-                    throw new NotImplementedException();
+                    Target.GetObservable(Control.DataContextProperty).Subscribe(dataContext =>
+                    {
+                        subject.Take(1).Subscribe(x => Target.SetValue(TargetProperty, x));
+                    });                    
+                    break;
                 case BindingMode.OneWayToSource:
                     Target.GetObservable(TargetProperty).Subscribe(subject);
                     break;

+ 32 - 0
tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs

@@ -53,6 +53,37 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
                 BindingPriority.LocalValue));
         }
 
+        [Fact]
+        public void OneTime_Binding_Should_Be_Set_Up()
+        {
+            var dataContext = new BehaviorSubject<object>(null);
+            var expression = new BehaviorSubject<object>(null);
+            var target = CreateTarget(dataContext: dataContext);
+            var binding = new XamlBinding
+            {
+                Target = target.Object,
+                TargetProperty = TextBox.TextProperty,
+                SourcePropertyPath = "Foo",
+                BindingMode = BindingMode.OneTime,
+            };
+
+            binding.Bind(expression);
+
+            target.Verify(x => x.SetValue(
+                (PerspexProperty)TextBox.TextProperty, 
+                null, 
+                BindingPriority.LocalValue));
+            target.ResetCalls();
+
+            expression.OnNext("foo");
+            dataContext.OnNext(1);
+
+            target.Verify(x => x.SetValue(
+                (PerspexProperty)TextBox.TextProperty,
+                "foo",
+                BindingPriority.LocalValue));
+        }
+
         [Fact]
         public void OneWayToSource_Binding_Should_Be_Set_Up()
         {
@@ -101,6 +132,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
             dataContext = dataContext ?? Observable.Never<object>().StartWith((object)null);
             text = text ?? Observable.Never<string>().StartWith((string)null);
 
+            result.Setup(x => x.GetObservable(Control.DataContextProperty)).Returns(dataContext);
             result.Setup(x => x.GetObservable((PerspexProperty)Control.DataContextProperty)).Returns(dataContext);
             result.Setup(x => x.GetObservable((PerspexProperty)TextBox.TextProperty)).Returns(text);
             return result;