Browse Source

Merged XamlBinding and XamlTemplateBinding.

Steven Kirk 10 years ago
parent
commit
785238bdf1

+ 25 - 0
src/Markup/Perspex.Markup.Xaml/Binding/RelativeSource.cs

@@ -0,0 +1,25 @@
+// 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.
+
+namespace Perspex.Markup.Xaml.Binding
+{
+    public enum RelativeSourceMode
+    {
+        DataContext,
+        TemplatedParent,
+    }
+
+    public class RelativeSource
+    {
+        public RelativeSource()
+        {
+        }
+
+        public RelativeSource(RelativeSourceMode mode)
+        {
+            Mode = mode;
+        }
+
+        public RelativeSourceMode Mode { get; set; }
+    }
+}

+ 37 - 5
src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs

@@ -23,10 +23,11 @@ namespace Perspex.Markup.Xaml.Binding
             _typeConverterProvider = typeConverterProvider;
         }
 
+        public BindingMode Mode { get; set; }
+        public BindingPriority Priority { get; set; }
+        public RelativeSource RelativeSource { get; set; }
         public string SourcePropertyPath { get; set; }
 
-        public BindingMode BindingMode { get; set; }
-
         public void Bind(IObservablePropertyBag instance, PerspexProperty property)
         {
             var subject = new ExpressionSubject(
@@ -35,7 +36,18 @@ namespace Perspex.Markup.Xaml.Binding
 
             if (subject != null)
             {
-                Bind(instance, property, subject);
+                if (RelativeSource?.Mode != RelativeSourceMode.TemplatedParent)
+                {
+                    Bind(instance, property, subject);
+                }
+                else
+                {
+                    instance.GetObservable(Control.TemplatedParentProperty)
+                        .Where(x => x != null)
+                        .OfType<PerspexObject>()
+                        .Take(1)
+                        .Subscribe(x => BindToTemplatedParent((PerspexObject)instance, property, x));
+                }
             }
         }
 
@@ -62,8 +74,8 @@ namespace Perspex.Markup.Xaml.Binding
 
         internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject<object> subject)
         {
-            var mode = BindingMode == BindingMode.Default ?
-                property.DefaultBindingMode : BindingMode;
+            var mode = Mode == BindingMode.Default ?
+                property.DefaultBindingMode : Mode;
 
             switch (mode)
             {
@@ -85,5 +97,25 @@ namespace Perspex.Markup.Xaml.Binding
                     break;
             }
         }
+
+        private void BindToTemplatedParent(
+            PerspexObject instance,
+            PerspexProperty targetProperty,
+            PerspexObject templatedParent)
+        {
+            var sourceProperty = PerspexPropertyRegistry.Instance.FindRegistered(
+                templatedParent,
+                SourcePropertyPath);
+
+            if (sourceProperty == null)
+            {
+                throw new InvalidOperationException(
+                    $"The property {SourcePropertyPath} could not be found on {templatedParent.GetType()}.");
+            }
+
+            instance.Bind(targetProperty, templatedParent.GetObservable(sourceProperty), BindingPriority.Style);
+            templatedParent.Bind(sourceProperty, instance.GetObservable(targetProperty), BindingPriority.Style);
+        }
+
     }
 }

+ 4 - 15
src/Markup/Perspex.Markup.Xaml/Binding/XamlBindingDefinition.cs

@@ -1,24 +1,13 @@
 // 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 Perspex.Controls;
-
 namespace Perspex.Markup.Xaml.Binding
 {
     public class XamlBindingDefinition
     {
-        public XamlBindingDefinition(
-            string sourcePropertyPath, 
-            BindingMode bindingMode,
-            bool isTemplateBinding = false)
-        {
-            SourcePropertyPath = sourcePropertyPath;
-            BindingMode = bindingMode;
-            IsTemplateBinding = isTemplateBinding;
-        }
-
-        public string SourcePropertyPath { get; }
-        public BindingMode BindingMode { get; }
-        public bool IsTemplateBinding { get; }
+        public BindingMode Mode { get; set; }
+        public BindingPriority Priority { get; set; }
+        public RelativeSource RelativeSource { get; set; }
+        public string SourcePropertyPath { get; set; }
     }
 }

+ 0 - 57
src/Markup/Perspex.Markup.Xaml/Binding/XamlTemplateBinding.cs

@@ -1,57 +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.Linq;
-using OmniXaml.TypeConversion;
-using Perspex.Controls;
-using Perspex.Styling;
-
-namespace Perspex.Markup.Xaml.Binding
-{
-    public class XamlTemplateBinding
-    {
-        private readonly ITypeConverterProvider _typeConverterProvider;
-
-        public XamlTemplateBinding()
-        {
-        }
-
-        public XamlTemplateBinding(ITypeConverterProvider typeConverterProvider)
-        {
-            _typeConverterProvider = typeConverterProvider;
-        }
-
-        public string SourcePropertyPath { get; set; }
-
-        public BindingMode BindingMode { get; set; }
-
-        public void Bind(PerspexObject instance, PerspexProperty targetProperty)
-        {
-            instance.GetObservable(Control.TemplatedParentProperty)
-                .Where(x => x != null)
-                .OfType<PerspexObject>()
-                .Take(1)
-                .Subscribe(x => BindToTemplatedParent(instance, targetProperty, x));
-        }
-
-        private void BindToTemplatedParent(
-            PerspexObject instance, 
-            PerspexProperty targetProperty,
-            PerspexObject templatedParent)
-        {
-            var sourceProperty = PerspexPropertyRegistry.Instance.FindRegistered(
-                templatedParent, 
-                SourcePropertyPath);
-
-            if (sourceProperty == null)
-            {
-                throw new InvalidOperationException(
-                    $"The property {SourcePropertyPath} could not be found on {templatedParent.GetType()}.");
-            }
-
-            instance.Bind(targetProperty, templatedParent.GetObservable(sourceProperty), BindingPriority.Style);
-            templatedParent.Bind(sourceProperty, instance.GetObservable(targetProperty), BindingPriority.Style);
-        }
-    }
-}

+ 7 - 18
src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs

@@ -109,26 +109,15 @@ namespace Perspex.Markup.Xaml.Context
                         $"Cannot find '{propertyName}' on '{instance.GetType()}");
                 }
 
-                if (!def.IsTemplateBinding)
+                var binding = new XamlBinding
                 {
-                    var binding = new XamlBinding
-                    {
-                        BindingMode = def.BindingMode,
-                        SourcePropertyPath = def.SourcePropertyPath,
-                    };
+                    Mode = def.Mode,
+                    Priority = def.Priority,
+                    RelativeSource = def.RelativeSource,
+                    SourcePropertyPath = def.SourcePropertyPath,
+                };
 
-                    binding.Bind(perspexObject, property);
-                }
-                else
-                {
-                    var binding = new XamlTemplateBinding
-                    {
-                        BindingMode = def.BindingMode,
-                        SourcePropertyPath = def.SourcePropertyPath,
-                    };
-
-                    binding.Bind(perspexObject, property);
-                }
+                binding.Bind(perspexObject, property);
             }
         }
 

+ 5 - 1
src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs

@@ -21,7 +21,11 @@ namespace Perspex.Markup.Xaml.MarkupExtensions
 
         public override object ProvideValue(MarkupExtensionContext extensionContext)
         {
-            return new XamlBindingDefinition(Path, Mode);
+            return new XamlBindingDefinition
+            {
+                Mode = Mode,
+                SourcePropertyPath = Path,
+            };
         }
 
         public string Path { get; set; }

+ 7 - 1
src/Markup/Perspex.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs

@@ -19,7 +19,13 @@ namespace Perspex.Markup.Xaml.MarkupExtensions
 
         public override object ProvideValue(MarkupExtensionContext extensionContext)
         {
-            return new XamlBindingDefinition(Path, Mode, true);
+            return new XamlBindingDefinition
+            {
+                Mode = Mode,
+                Priority = BindingPriority.TemplatedParent,
+                RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
+                SourcePropertyPath = Path,
+            };
         }
 
         public string Path { get; set; }

+ 1 - 0
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@@ -38,6 +38,7 @@
     <Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
       <Link>Properties\SharedAssemblyInfo.cs</Link>
     </Compile>
+    <Compile Include="Binding\RelativeSource.cs" />
     <Compile Include="Binding\SourceBindingEndpoint.cs" />
     <Compile Include="Binding\TargetBindingEndpoint.cs" />
     <Compile Include="Binding\XamlTemplateBinding.cs" />

+ 2 - 2
tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs

@@ -404,13 +404,13 @@ namespace Perspex.Controls.UnitTests.Primitives
             var itemsBinding = new XamlBinding
             {
                 SourcePropertyPath = "Items",
-                BindingMode = BindingMode.OneWay,
+                Mode = BindingMode.OneWay,
             };
 
             var selectedItemsBinding = new XamlBinding
             {
                 SourcePropertyPath = "SelectedItems",
-                BindingMode = BindingMode.OneWay,
+                Mode = BindingMode.OneWay,
             };
 
             // Bind Items and SelectedItems to the VM.

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

@@ -20,7 +20,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
             var binding = new XamlBinding
             {
                 SourcePropertyPath = "Foo",
-                BindingMode = BindingMode.OneWay,
+                Mode = BindingMode.OneWay,
             };
 
             binding.Bind(target.Object, TextBox.TextProperty);
@@ -38,7 +38,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
             var binding = new XamlBinding
             {
                 SourcePropertyPath = "Foo",
-                BindingMode = BindingMode.TwoWay,
+                Mode = BindingMode.TwoWay,
             };
 
             binding.Bind(target.Object, TextBox.TextProperty);
@@ -58,7 +58,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
             var binding = new XamlBinding
             {
                 SourcePropertyPath = "Foo",
-                BindingMode = BindingMode.OneTime,
+                Mode = BindingMode.OneTime,
             };
 
             binding.Bind(target.Object, TextBox.TextProperty, expression);
@@ -87,7 +87,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
             var binding = new XamlBinding
             {
                 SourcePropertyPath = "Foo",
-                BindingMode = BindingMode.OneWayToSource,
+                Mode = BindingMode.OneWayToSource,
             };
 
             binding.Bind(target.Object, TextBox.TextProperty, expression.Object);

+ 2 - 2
tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs

@@ -31,13 +31,13 @@ namespace Perspex.Xaml.Base.UnitTest
             var fooBinding = new XamlBinding
             {
                 SourcePropertyPath = "Foo",
-                BindingMode = BindingMode.TwoWay,
+                Mode = BindingMode.TwoWay,
             };
 
             var barBinding = new XamlBinding
             {
                 SourcePropertyPath = "Bar",
-                BindingMode = BindingMode.TwoWay,
+                Mode = BindingMode.TwoWay,
             };
 
             // Bind Foo and Bar to the VM.