diff --git a/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs b/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs index 1ddd23e372..4bc0192c9f 100644 --- a/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs +++ b/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs @@ -19,6 +19,26 @@ namespace Perspex.Markup.Binding Nodes = ExpressionNodeBuilder.Build(expression); } + public bool SetValue(object value) + { + var last = Nodes.Last() as PropertyAccessorNode; + + if (last != null) + { + try + { + IncrementCount(); + return last.SetValue(value); + } + finally + { + DecrementCount(); + } + } + + return false; + } + public object Root { get; } public IList Nodes { get; } diff --git a/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs b/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs index 1c48d272d8..351879d1b4 100644 --- a/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs +++ b/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs @@ -16,6 +16,17 @@ namespace Perspex.Markup.Binding PropertyName = propertyName; } + public bool SetValue(object value) + { + if (_propertyInfo != null) + { + _propertyInfo.SetValue(Target, value); + return true; + } + + return false; + } + public string PropertyName { get; } protected override void SubscribeAndUpdate(object target) diff --git a/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests.cs b/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests.cs index f564788f56..79be969d4f 100644 --- a/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests.cs +++ b/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests.cs @@ -142,6 +142,53 @@ namespace Perspex.Markup.UnitTests.Binding Assert.Equal(0, old.SubscriptionCount); } + [Fact] + public void SetValue_Should_Set_Simple_Property_Value() + { + var data = new Class1 { Foo = "foo" }; + var target = new ExpressionObserver(data, "Foo"); + + Assert.True(target.SetValue("bar")); + Assert.Equal("bar", data.Foo); + } + + [Fact] + public void SetValue_Should_Set_Property_At_The_End_Of_Chain() + { + var data = new Class1 { Next = new Class2 { Bar = "bar" } }; + var target = new ExpressionObserver(data, "Next.Bar"); + + Assert.True(target.SetValue("baz")); + Assert.Equal("baz", ((Class2)data.Next).Bar); + } + + [Fact] + public void SetValue_Should_Return_False_For_Missing_Property() + { + var data = new Class1 { Next = new WithoutBar()}; + var target = new ExpressionObserver(data, "Next.Bar"); + + Assert.False(target.SetValue("baz")); + } + + [Fact] + public void SetValue_Should_Return_False_For_Missing_Object() + { + var data = new Class1(); + var target = new ExpressionObserver(data, "Next.Bar"); + + Assert.False(target.SetValue("baz")); + } + + [Fact] + public void SetValue_Should_Throw_For_Wrong_Type() + { + var data = new Class1 { Foo = "foo" }; + var target = new ExpressionObserver(data, "Foo"); + + Assert.Throws(() => target.SetValue(1.2)); + } + private interface INext { int SubscriptionCount { get; } diff --git a/tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj b/tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj index 675e280df9..909f67155f 100644 --- a/tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj +++ b/tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj @@ -86,6 +86,9 @@ Perspex.Markup + + +