diff --git a/samples/BindingTest/App.cs b/samples/BindingTest/App.cs index 8399166015..70cfcfb44b 100644 --- a/samples/BindingTest/App.cs +++ b/samples/BindingTest/App.cs @@ -18,6 +18,7 @@ namespace BindingTest Log.Logger = new LoggerConfiguration() .Filter.ByIncludingOnly(Matching.WithProperty("Area", "Property")) + .Filter.ByIncludingOnly(Matching.WithProperty("Property", "Text")) .MinimumLevel.Verbose() .WriteTo.Trace(outputTemplate: "[{Id:X8}] [{SourceContext}] {Message}") .CreateLogger(); diff --git a/samples/XamlTestApplication/Views/MainWindow.paml b/samples/XamlTestApplication/Views/MainWindow.paml index 08ca945b96..9fe6a760a8 100644 --- a/samples/XamlTestApplication/Views/MainWindow.paml +++ b/samples/XamlTestApplication/Views/MainWindow.paml @@ -59,7 +59,7 @@ - + @@ -69,16 +69,16 @@ - + --> + diff --git a/src/Markup/Perspex.Markup.Xaml/Binding/PerspexPropertyBinder.cs b/src/Markup/Perspex.Markup.Xaml/Binding/PerspexPropertyBinder.cs index b0e2029ee0..9e4eee4b84 100644 --- a/src/Markup/Perspex.Markup.Xaml/Binding/PerspexPropertyBinder.cs +++ b/src/Markup/Perspex.Markup.Xaml/Binding/PerspexPropertyBinder.cs @@ -22,38 +22,41 @@ namespace Perspex.Markup.Xaml.Binding public XamlBinding GetBinding(PerspexObject po, PerspexProperty pp) { - return _bindings.First(xamlBinding => xamlBinding.Target == po && xamlBinding.TargetProperty == pp); + throw new NotImplementedException(); + //return _bindings.First(xamlBinding => xamlBinding.Target == po && xamlBinding.TargetProperty == pp); } public IEnumerable GetBindings(PerspexObject source) { - return from binding in _bindings - where binding.Target == source - select binding; + throw new NotImplementedException(); + //return from binding in _bindings + // where binding.Target == source + // select binding; } public XamlBinding Create(XamlBindingDefinition xamlBinding) { - if (xamlBinding.Target == null) - { - throw new InvalidOperationException(); - } - - if (xamlBinding.TargetProperty == null) - { - throw new InvalidOperationException(); - } - - var binding = new XamlBinding(TypeConverterProvider) - { - BindingMode = xamlBinding.BindingMode, - SourcePropertyPath = xamlBinding.SourcePropertyPath, - Target = xamlBinding.Target, - TargetProperty = xamlBinding.TargetProperty - }; - - _bindings.Add(binding); - return binding; + throw new NotImplementedException(); + //if (xamlBinding.Target == null) + //{ + // throw new InvalidOperationException(); + //} + + //if (xamlBinding.TargetProperty == null) + //{ + // throw new InvalidOperationException(); + //} + + //var binding = new XamlBinding(TypeConverterProvider) + //{ + // BindingMode = xamlBinding.BindingMode, + // SourcePropertyPath = xamlBinding.SourcePropertyPath, + // Target = xamlBinding.Target, + // TargetProperty = xamlBinding.TargetProperty + //}; + + //_bindings.Add(binding); + //return binding; } } } \ No newline at end of file diff --git a/src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs b/src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs index 3e3e978f7c..3bf709e928 100644 --- a/src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs +++ b/src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs @@ -23,49 +23,46 @@ namespace Perspex.Markup.Xaml.Binding _typeConverterProvider = typeConverterProvider; } - public IObservablePropertyBag Target { get; set; } - - public PerspexProperty TargetProperty { get; set; } - public string SourcePropertyPath { get; set; } public BindingMode BindingMode { get; set; } - public void Bind() + public void Bind(IObservablePropertyBag instance, PerspexProperty property) { - Bind(new ExpressionSubject(CreateExpressionObserver())); + var subject = new ExpressionSubject(CreateExpressionObserver(instance)); + Bind(instance, property, subject); } - public ExpressionObserver CreateExpressionObserver() + public ExpressionObserver CreateExpressionObserver(IObservablePropertyBag instance) { var result = new ExpressionObserver(null, SourcePropertyPath); - var dataContext = Target.GetObservable(Control.DataContextProperty); + var dataContext = instance.GetObservable(Control.DataContextProperty); dataContext.Subscribe(x => result.Root = x); return result; } - internal void Bind(ISubject subject) + internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject subject) { var mode = BindingMode == BindingMode.Default ? - TargetProperty.DefaultBindingMode : BindingMode; + property.DefaultBindingMode : BindingMode; switch (mode) { case BindingMode.Default: case BindingMode.OneWay: - Target.Bind(TargetProperty, subject); + target.Bind(property, subject); break; case BindingMode.TwoWay: - Target.BindTwoWay(TargetProperty, subject); + target.BindTwoWay(property, subject); break; case BindingMode.OneTime: - Target.GetObservable(Control.DataContextProperty).Subscribe(dataContext => + target.GetObservable(Control.DataContextProperty).Subscribe(dataContext => { - subject.Take(1).Subscribe(x => Target.SetValue(TargetProperty, x)); + subject.Take(1).Subscribe(x => target.SetValue(property, x)); }); break; case BindingMode.OneWayToSource: - Target.GetObservable(TargetProperty).Subscribe(subject); + target.GetObservable(property).Subscribe(subject); break; } } diff --git a/src/Markup/Perspex.Markup.Xaml/Binding/XamlBindingDefinition.cs b/src/Markup/Perspex.Markup.Xaml/Binding/XamlBindingDefinition.cs index da0c6d633e..c571036d4d 100644 --- a/src/Markup/Perspex.Markup.Xaml/Binding/XamlBindingDefinition.cs +++ b/src/Markup/Perspex.Markup.Xaml/Binding/XamlBindingDefinition.cs @@ -8,19 +8,13 @@ namespace Perspex.Markup.Xaml.Binding public class XamlBindingDefinition { public XamlBindingDefinition( - Control target, - PerspexProperty targetProperty, string sourcePropertyPath, BindingMode bindingMode) { - Target = target; - TargetProperty = targetProperty; SourcePropertyPath = sourcePropertyPath; BindingMode = bindingMode; } - public Control Target { get; } - public PerspexProperty TargetProperty { get; } public string SourcePropertyPath { get; } public BindingMode BindingMode { get; } } diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs index 908fcd22fe..1bb324c5a8 100644 --- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs +++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Linq; using System.Reactive.Linq; using Glass; using OmniXaml.ObjectAssembler; @@ -27,7 +28,7 @@ namespace Perspex.Markup.Xaml.Context { if (value is XamlBindingDefinition) { - HandleXamlBindingDefinition((XamlBindingDefinition)value); + HandleXamlBindingDefinition(instance, (XamlBindingDefinition)value); } else if (IsPerspexProperty) { @@ -54,17 +55,32 @@ namespace Perspex.Markup.Xaml.Context po.SetValue(pp, value); } - private void HandleXamlBindingDefinition(XamlBindingDefinition def) + private void HandleXamlBindingDefinition(object instance, XamlBindingDefinition def) { + var perspexObject = instance as PerspexObject; + + if (perspexObject == null) + { + throw new InvalidOperationException( + $"Cannot bind to an object of type '{instance.GetType()}"); + } + + var property = perspexObject.GetRegisteredProperties() + .FirstOrDefault(x => x.Name == _xamlMember.Name); + + if (property == null) + { + throw new InvalidOperationException( + $"Cannot find '{_xamlMember.Name}' on '{instance.GetType()}"); + } + var binding = new XamlBinding(_propertyBinder.TypeConverterProvider) { BindingMode = def.BindingMode, SourcePropertyPath = def.SourcePropertyPath, - Target = def.Target, - TargetProperty = def.TargetProperty, }; - binding.Bind(); + binding.Bind(perspexObject, property); } private void BindToDataContextWhenItsSet(XamlBindingDefinition definition) diff --git a/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs index 5c124de956..7abc09ef89 100644 --- a/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs @@ -21,11 +21,7 @@ namespace Perspex.Markup.Xaml.MarkupExtensions public override object ProvideValue(MarkupExtensionContext extensionContext) { - var target = extensionContext.TargetObject as Control; - var targetProperty = extensionContext.TargetProperty; - var targetPropertyName = targetProperty.Name; - var perspexProperty = target.GetRegisteredProperties().First(property => property.Name == targetPropertyName); - return new XamlBindingDefinition(target, perspexProperty, Path, Mode); + return new XamlBindingDefinition(Path, Mode); } public string Path { get; set; } diff --git a/tests/Perspex.Markup.Xaml.UnitTests/BinderTest.cs b/tests/Perspex.Markup.Xaml.UnitTests/BinderTest.cs deleted file mode 100644 index a39f4b0667..0000000000 --- a/tests/Perspex.Markup.Xaml.UnitTests/BinderTest.cs +++ /dev/null @@ -1,27 +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 Moq; -using Perspex.Markup.Xaml.Binding; -using OmniXaml.TypeConversion; -using Xunit; - -namespace Perspex.Xaml.Base.UnitTest -{ - public class BinderTest - { - [Fact] - public void NullTarget_Throws() - { - var typeConverter = new Mock(); - var perspexPropertyBinder = new PerspexPropertyBinder(typeConverter.Object); - var bindingDefinitionBuilder = new BindingDefinitionBuilder(); - var binding = bindingDefinitionBuilder - .WithNullTarget() - .Build(); - - var exception = Assert.Throws(() => perspexPropertyBinder.Create(binding)); - } - } -} diff --git a/tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs b/tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs index 321df1b475..97e0dc7741 100644 --- a/tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs +++ b/tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs @@ -19,13 +19,11 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding var target = CreateTarget(); var binding = new XamlBinding { - Target = target.Object, - TargetProperty = TextBox.TextProperty, SourcePropertyPath = "Foo", BindingMode = BindingMode.OneWay, }; - binding.Bind(); + binding.Bind(target.Object, TextBox.TextProperty); target.Verify(x => x.Bind( TextBox.TextProperty, @@ -39,13 +37,11 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding var target = CreateTarget(); var binding = new XamlBinding { - Target = target.Object, - TargetProperty = TextBox.TextProperty, SourcePropertyPath = "Foo", BindingMode = BindingMode.TwoWay, }; - binding.Bind(); + binding.Bind(target.Object, TextBox.TextProperty); target.Verify(x => x.BindTwoWay( TextBox.TextProperty, @@ -61,13 +57,11 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding var target = CreateTarget(dataContext: dataContext); var binding = new XamlBinding { - Target = target.Object, - TargetProperty = TextBox.TextProperty, SourcePropertyPath = "Foo", BindingMode = BindingMode.OneTime, }; - binding.Bind(expression); + binding.Bind(target.Object, TextBox.TextProperty, expression); target.Verify(x => x.SetValue( (PerspexProperty)TextBox.TextProperty, @@ -92,13 +86,11 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding var target = CreateTarget(text: textObservable.Object); var binding = new XamlBinding { - Target = target.Object, - TargetProperty = TextBox.TextProperty, SourcePropertyPath = "Foo", BindingMode = BindingMode.OneWayToSource, }; - binding.Bind(expression.Object); + binding.Bind(target.Object, TextBox.TextProperty, expression.Object); textObservable.Verify(x => x.Subscribe(expression.Object)); } @@ -109,12 +101,10 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding var target = CreateTarget(null); var binding = new XamlBinding { - Target = target.Object, - TargetProperty = TextBox.TextProperty, SourcePropertyPath = "Foo", }; - binding.Bind(); + binding.Bind(target.Object, TextBox.TextProperty); // Default for TextBox.Text is two-way. target.Verify(x => x.BindTwoWay( diff --git a/tests/Perspex.Markup.Xaml.UnitTests/BindingDefinitionBuilder.cs b/tests/Perspex.Markup.Xaml.UnitTests/BindingDefinitionBuilder.cs deleted file mode 100644 index 7e986201e3..0000000000 --- a/tests/Perspex.Markup.Xaml.UnitTests/BindingDefinitionBuilder.cs +++ /dev/null @@ -1,36 +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 Perspex.Controls; -using Perspex.Markup.Xaml.Binding; - -namespace Perspex.Xaml.Base.UnitTest -{ - public class BindingDefinitionBuilder - { - private readonly BindingMode _bindingMode; - private readonly string _sourcePropertyPath; - private Control _target; - - public BindingDefinitionBuilder() - { - _bindingMode = BindingMode.Default; - _sourcePropertyPath = string.Empty; - } - - public BindingDefinitionBuilder WithNullTarget() - { - _target = null; - return this; - } - - public XamlBindingDefinition Build() - { - return new XamlBindingDefinition( - bindingMode: _bindingMode, - sourcePropertyPath: _sourcePropertyPath, - target: _target, - targetProperty: null); - } - } -} \ No newline at end of file diff --git a/tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj b/tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj index e014a04a48..2ac180603f 100644 --- a/tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj +++ b/tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj @@ -88,7 +88,6 @@ - @@ -103,7 +102,6 @@ -