diff --git a/Tests/Perspex.Base.UnitTests/GlobalSuppressions.cs b/Tests/Perspex.Base.UnitTests/GlobalSuppressions.cs
index c4e71ed365..5b748a54d0 100644
--- a/Tests/Perspex.Base.UnitTests/GlobalSuppressions.cs
+++ b/Tests/Perspex.Base.UnitTests/GlobalSuppressions.cs
@@ -3,6 +3,10 @@
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
+ "StyleCop.CSharp.MaintainabilityRules",
+ "SA1401:Fields must be private",
+ Justification = "PerspexProperty fields should not be private.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1600:Elements must be documented",
diff --git a/Tests/Perspex.Base.UnitTests/Perspex.Base.UnitTests.csproj b/Tests/Perspex.Base.UnitTests/Perspex.Base.UnitTests.csproj
index e0ed27530f..d1fa0f4dd0 100644
--- a/Tests/Perspex.Base.UnitTests/Perspex.Base.UnitTests.csproj
+++ b/Tests/Perspex.Base.UnitTests/Perspex.Base.UnitTests.csproj
@@ -79,9 +79,15 @@
+
+
+
+
+
+
+
-
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests.cs
deleted file mode 100644
index 88f14bd565..0000000000
--- a/Tests/Perspex.Base.UnitTests/PerspexObjectTests.cs
+++ /dev/null
@@ -1,698 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2013 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
-
-namespace Perspex.Base.UnitTests
-{
- using System;
- using System.Linq;
- using System.Reactive.Linq;
- using System.Reactive.Subjects;
- using Xunit;
-
- public class PerspexObjectTests
- {
- public PerspexObjectTests()
- {
- // Ensure properties are registered.
- PerspexProperty p;
- p = Class1.FooProperty;
- p = Class2.BarProperty;
- }
-
- [Fact]
- public void GetProperties_Returns_Registered_Properties()
- {
- string[] names = PerspexObject.GetProperties(typeof(Class1)).Select(x => x.Name).ToArray();
-
- Assert.Equal(new[] { "Foo", "Baz", "Qux" }, names);
- }
-
- [Fact]
- public void GetProperties_Returns_Registered_Properties_For_Base_Types()
- {
- string[] names = PerspexObject.GetProperties(typeof(Class2)).Select(x => x.Name).ToArray();
-
- Assert.Equal(new[] { "Bar", "Flob", "Fred", "Foo", "Baz", "Qux" }, names);
- }
-
- [Fact]
- public void GetValue_Returns_Default_Value()
- {
- Class1 target = new Class1();
-
- Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void GetValue_Returns_Overridden_Default_Value()
- {
- Class2 target = new Class2();
-
- Assert.Equal("foooverride", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void GetValue_Returns_Set_Value()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.FooProperty, "newvalue");
-
- Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void GetValue_Returns_Inherited_Value()
- {
- Class1 parent = new Class1();
- Class2 child = new Class2 { Parent = parent };
-
- parent.SetValue(Class1.BazProperty, "changed");
-
- Assert.Equal("changed", child.GetValue(Class1.BazProperty));
- }
-
- [Fact]
- public void ClearValue_Clears_Value()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.FooProperty, "newvalue");
- target.ClearValue(Class1.FooProperty);
-
- Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void SetValue_Sets_Value()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.FooProperty, "newvalue");
-
- Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void SetValue_Raises_PropertyChanged()
- {
- Class1 target = new Class1();
- bool raised = false;
-
- target.PropertyChanged += (s, e) =>
- {
- raised = s == target &&
- e.Property == Class1.FooProperty &&
- (string)e.OldValue == "foodefault" &&
- (string)e.NewValue == "newvalue";
- };
-
- target.SetValue(Class1.FooProperty, "newvalue");
-
- Assert.True(raised);
- }
-
- [Fact]
- public void SetValue_Doesnt_Raise_PropertyChanged_If_Value_Not_Changed()
- {
- Class1 target = new Class1();
- bool raised = false;
-
- target.SetValue(Class1.FooProperty, "bar");
-
- target.PropertyChanged += (s, e) =>
- {
- raised = true;
- };
-
- target.SetValue(Class1.FooProperty, "bar");
-
- Assert.False(raised);
- }
-
- [Fact]
- public void SetValue_Doesnt_Raise_PropertyChanged_If_Value_Not_Changed_From_Default()
- {
- Class1 target = new Class1();
- bool raised = false;
-
- target.PropertyChanged += (s, e) =>
- {
- raised = true;
- };
-
- target.SetValue(Class1.FooProperty, "foodefault");
-
- Assert.False(raised);
- }
-
- [Fact]
- public void SetValue_Throws_Exception_For_Unregistered_Property()
- {
- Class1 target = new Class1();
-
- Assert.Throws(() =>
- {
- target.SetValue(Class2.BarProperty, "invalid");
- });
- }
-
- [Fact]
- public void SetValue_Throws_Exception_For_Invalid_Value_Type()
- {
- Class1 target = new Class1();
-
- Assert.Throws(() =>
- {
- target.SetValue(Class1.FooProperty, 123);
- });
- }
-
- [Fact]
- public void SetValue_Of_Integer_On_Double_Property_Works()
- {
- Class2 target = new Class2();
-
- target.SetValue((PerspexProperty)Class2.FlobProperty, 4);
-
- var value = target.GetValue(Class2.FlobProperty);
- Assert.IsType(value);
- Assert.Equal(4, value);
- }
-
- [Fact]
- public void SetValue_Respects_Implicit_Conversions()
- {
- Class2 target = new Class2();
-
- target.SetValue((PerspexProperty)Class2.FlobProperty, new ImplictDouble(4));
-
- var value = target.GetValue(Class2.FlobProperty);
- Assert.IsType(value);
- Assert.Equal(4, value);
- }
-
- [Fact]
- public void SetValue_Can_Convert_To_Nullable()
- {
- Class2 target = new Class2();
-
- target.SetValue((PerspexProperty)Class2.FredProperty, 4.0);
-
- var value = target.GetValue(Class2.FredProperty);
- Assert.IsType(value);
- Assert.Equal(4, value);
- }
-
- [Fact]
- public void SetValue_Causes_Coercion()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.QuxProperty, 5);
- Assert.Equal(5, target.GetValue(Class1.QuxProperty));
- target.SetValue(Class1.QuxProperty, -5);
- Assert.Equal(0, target.GetValue(Class1.QuxProperty));
- target.SetValue(Class1.QuxProperty, 15);
- Assert.Equal(10, target.GetValue(Class1.QuxProperty));
- }
-
- [Fact]
- public void SetValue_Respects_Priority()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.FooProperty, "one", BindingPriority.TemplatedParent);
- Assert.Equal("one", target.GetValue(Class1.FooProperty));
- target.SetValue(Class1.FooProperty, "two", BindingPriority.Style);
- Assert.Equal("one", target.GetValue(Class1.FooProperty));
- target.SetValue(Class1.FooProperty, "three", BindingPriority.StyleTrigger);
- Assert.Equal("three", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void CoerceValue_Causes_Recoercion()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.QuxProperty, 7);
- Assert.Equal(7, target.GetValue(Class1.QuxProperty));
- target.MaxQux = 5;
- target.CoerceValue(Class1.QuxProperty);
- }
-
- [Fact]
- public void GetObservable_Returns_Initial_Value()
- {
- Class1 target = new Class1();
- int raised = 0;
-
- target.GetObservable(Class1.FooProperty).Subscribe(x =>
- {
- if (x == "foodefault")
- {
- ++raised;
- }
- });
-
- Assert.Equal(1, raised);
- }
-
- [Fact]
- public void GetObservable_Returns_Property_Change()
- {
- Class1 target = new Class1();
- bool raised = false;
-
- target.GetObservable(Class1.FooProperty).Subscribe(x => raised = x == "newvalue");
- raised = false;
- target.SetValue(Class1.FooProperty, "newvalue");
-
- Assert.True(raised);
- }
-
- [Fact]
- public void GetObservable_Returns_Property_Change_Only_For_Correct_Property()
- {
- Class2 target = new Class2();
- bool raised = false;
-
- target.GetObservable(Class1.FooProperty).Subscribe(x => raised = true);
- raised = false;
- target.SetValue(Class2.BarProperty, "newvalue");
-
- Assert.False(raised);
- }
-
- [Fact]
- public void GetObservable_Dispose_Stops_Property_Changes()
- {
- Class1 target = new Class1();
- bool raised = false;
-
- target.GetObservable(Class1.FooProperty)
- .Subscribe(x => raised = true)
- .Dispose();
- raised = false;
- target.SetValue(Class1.FooProperty, "newvalue");
-
- Assert.False(raised);
- }
-
- [Fact]
- public void Setting_InheritanceParent_Raises_PropertyChanged_When_Value_Changed_In_Parent()
- {
- bool raised = false;
-
- Class1 parent = new Class1();
- parent.SetValue(Class1.BazProperty, "changed");
-
- Class2 child = new Class2();
- child.PropertyChanged += (s, e) =>
- raised = s == child &&
- e.Property == Class1.BazProperty &&
- (string)e.OldValue == "bazdefault" &&
- (string)e.NewValue == "changed";
-
- child.Parent = parent;
-
- Assert.True(raised);
- }
-
- [Fact]
- public void Setting_InheritanceParent_Doesnt_Raise_PropertyChanged_When_Local_Value_Set()
- {
- bool raised = false;
-
- Class1 parent = new Class1();
- parent.SetValue(Class1.BazProperty, "changed");
-
- Class2 child = new Class2();
- child.SetValue(Class1.BazProperty, "localvalue");
- child.PropertyChanged += (s, e) => raised = true;
-
- child.Parent = parent;
-
- Assert.False(raised);
- }
-
- [Fact]
- public void Setting_Value_In_InheritanceParent_Raises_PropertyChanged()
- {
- bool raised = false;
-
- Class1 parent = new Class1();
-
- Class2 child = new Class2();
- child.PropertyChanged += (s, e) =>
- raised = s == child &&
- e.Property == Class1.BazProperty &&
- (string)e.OldValue == "bazdefault" &&
- (string)e.NewValue == "changed";
- child.Parent = parent;
-
- parent.SetValue(Class1.BazProperty, "changed");
-
- Assert.True(raised);
- }
-
- [Fact]
- public void Bind_Sets_Current_Value()
- {
- Class1 target = new Class1();
- Class1 source = new Class1();
-
- source.SetValue(Class1.FooProperty, "initial");
- target.Bind(Class1.FooProperty, source.GetObservable(Class1.FooProperty));
-
- Assert.Equal("initial", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void Bind_NonGeneric_Sets_Current_Value()
- {
- Class1 target = new Class1();
- Class1 source = new Class1();
-
- source.SetValue(Class1.FooProperty, "initial");
- target.Bind((PerspexProperty)Class1.FooProperty, source.GetObservable(Class1.FooProperty));
-
- Assert.Equal("initial", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void Bind_Throws_Exception_For_Unregistered_Property()
- {
- Class1 target = new Class1();
-
- Assert.Throws(() =>
- {
- target.Bind(Class2.BarProperty, Observable.Return("foo"));
- });
- }
-
- [Fact]
- public void Bind_Sets_Subsequent_Value()
- {
- Class1 target = new Class1();
- Class1 source = new Class1();
-
- source.SetValue(Class1.FooProperty, "initial");
- target.Bind(Class1.FooProperty, source.GetObservable(Class1.FooProperty));
- source.SetValue(Class1.FooProperty, "subsequent");
-
- Assert.Equal("subsequent", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void Bind_Throws_Exception_For_Invalid_Value_Type()
- {
- Class1 target = new Class1();
-
- Assert.Throws(() =>
- {
- target.Bind((PerspexProperty)Class1.FooProperty, Observable.Return((object)123));
- });
- }
-
- [Fact]
- public void Two_Way_Binding_Works()
- {
- Class1 obj1 = new Class1();
- Class1 obj2 = new Class1();
-
- obj1.SetValue(Class1.FooProperty, "initial1");
- obj2.SetValue(Class1.FooProperty, "initial2");
-
- obj1.Bind(Class1.FooProperty, obj2.GetObservable(Class1.FooProperty));
- obj2.Bind(Class1.FooProperty, obj1.GetObservable(Class1.FooProperty));
-
- Assert.Equal("initial2", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("initial2", obj2.GetValue(Class1.FooProperty));
-
- obj1.SetValue(Class1.FooProperty, "first");
-
- Assert.Equal("first", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("first", obj2.GetValue(Class1.FooProperty));
-
- obj2.SetValue(Class1.FooProperty, "second");
-
- Assert.Equal("second", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("second", obj2.GetValue(Class1.FooProperty));
-
- obj1.SetValue(Class1.FooProperty, "third");
-
- Assert.Equal("third", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("third", obj2.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void Two_Way_Binding_With_Priority_Works()
- {
- Class1 obj1 = new Class1();
- Class1 obj2 = new Class1();
-
- obj1.SetValue(Class1.FooProperty, "initial1", BindingPriority.Style);
- obj2.SetValue(Class1.FooProperty, "initial2", BindingPriority.Style);
-
- obj1.Bind(Class1.FooProperty, obj2.GetObservable(Class1.FooProperty), BindingPriority.Style);
- obj2.Bind(Class1.FooProperty, obj1.GetObservable(Class1.FooProperty), BindingPriority.Style);
-
- Assert.Equal("initial2", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("initial2", obj2.GetValue(Class1.FooProperty));
-
- obj1.SetValue(Class1.FooProperty, "first", BindingPriority.Style);
-
- Assert.Equal("first", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("first", obj2.GetValue(Class1.FooProperty));
-
- obj2.SetValue(Class1.FooProperty, "second", BindingPriority.Style);
-
- Assert.Equal("second", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("second", obj2.GetValue(Class1.FooProperty));
-
- obj1.SetValue(Class1.FooProperty, "third", BindingPriority.Style);
-
- Assert.Equal("third", obj1.GetValue(Class1.FooProperty));
- Assert.Equal("third", obj2.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void BindTwoWay_Gets_Initial_Value_From_Source()
- {
- Class1 source = new Class1();
- Class1 target = new Class1();
-
- source.SetValue(Class1.FooProperty, "initial");
- target.BindTwoWay(Class1.FooProperty, source, Class1.FooProperty);
-
- Assert.Equal("initial", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void BindTwoWay_Updates_Values()
- {
- Class1 source = new Class1();
- Class1 target = new Class1();
-
- source.SetValue(Class1.FooProperty, "first");
- target.BindTwoWay(Class1.FooProperty, source, Class1.FooProperty);
-
- Assert.Equal("first", target.GetValue(Class1.FooProperty));
- source.SetValue(Class1.FooProperty, "second");
- Assert.Equal("second", target.GetValue(Class1.FooProperty));
- target.SetValue(Class1.FooProperty, "third");
- Assert.Equal("third", source.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void Setting_UnsetValue_Reverts_To_Default_Value()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.FooProperty, "newvalue");
- target.SetValue(Class1.FooProperty, PerspexProperty.UnsetValue);
-
- Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void Local_Binding_Overwrites_Local_Value()
- {
- var target = new Class1();
- var binding = new Subject();
-
- target.Bind(Class1.FooProperty, binding);
-
- binding.OnNext("first");
- Assert.Equal("first", target.GetValue(Class1.FooProperty));
-
- target.SetValue(Class1.FooProperty, "second");
- Assert.Equal("second", target.GetValue(Class1.FooProperty));
-
- binding.OnNext("third");
- Assert.Equal("third", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void StyleBinding_Overrides_Default_Value()
- {
- Class1 target = new Class1();
-
- target.Bind(Class1.FooProperty, this.Single("stylevalue"), BindingPriority.Style);
-
- Assert.Equal("stylevalue", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void this_Operator_Returns_Value_Property()
- {
- Class1 target = new Class1();
-
- target.SetValue(Class1.FooProperty, "newvalue");
-
- Assert.Equal("newvalue", target[Class1.FooProperty]);
- }
-
- [Fact]
- public void this_Operator_Sets_Value_Property()
- {
- Class1 target = new Class1();
-
- target[Class1.FooProperty] = "newvalue";
-
- Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void this_Operator_Doesnt_Accept_Observable()
- {
- Class1 target = new Class1();
-
- Assert.Throws(() =>
- {
- target[Class1.FooProperty] = Observable.Return("newvalue");
- });
- }
-
- [Fact]
- public void this_Operator_Binds_One_Way()
- {
- Class1 target1 = new Class1();
- Class1 target2 = new Class1();
- Binding binding = Class1.FooProperty.Bind().WithMode(BindingMode.OneWay);
-
- target1.SetValue(Class1.FooProperty, "first");
- target2[binding] = target1[!Class1.FooProperty];
- target1.SetValue(Class1.FooProperty, "second");
-
- Assert.Equal("second", target2.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void this_Operator_Binds_Two_Way()
- {
- Class1 target1 = new Class1();
- Class1 target2 = new Class1();
- Binding binding = Class1.FooProperty.Bind().WithMode(BindingMode.TwoWay);
-
- target1.SetValue(Class1.FooProperty, "first");
- target2[binding] = target1[!Class1.FooProperty];
- Assert.Equal("first", target2.GetValue(Class1.FooProperty));
- target1.SetValue(Class1.FooProperty, "second");
- Assert.Equal("second", target2.GetValue(Class1.FooProperty));
- target2.SetValue(Class1.FooProperty, "third");
- Assert.Equal("third", target1.GetValue(Class1.FooProperty));
- }
-
- [Fact]
- public void this_Operator_Binds_One_Time()
- {
- Class1 target1 = new Class1();
- Class1 target2 = new Class1();
- Binding binding = Class1.FooProperty.Bind().WithMode(BindingMode.OneTime);
-
- target1.SetValue(Class1.FooProperty, "first");
- target2[binding] = target1[!Class1.FooProperty];
- target1.SetValue(Class1.FooProperty, "second");
-
- Assert.Equal("first", target2.GetValue(Class1.FooProperty));
- }
-
- ///
- /// Returns an observable that returns a single value but does not complete.
- ///
- /// The type of the observable.
- /// The value.
- /// The observable.
- private IObservable Single(T value)
- {
- return Observable.Never().StartWith(value);
- }
-
- private class Class1 : PerspexObject
- {
- public static readonly PerspexProperty FooProperty =
- PerspexProperty.Register("Foo", "foodefault");
-
- public static readonly PerspexProperty BazProperty =
- PerspexProperty.Register("Baz", "bazdefault", true);
-
- public static readonly PerspexProperty QuxProperty =
- PerspexProperty.Register("Qux", coerce: Coerce);
-
- public Class1()
- {
- this.MaxQux = 10;
- }
-
- public int MaxQux { get; set; }
-
- private static int Coerce(PerspexObject instance, int value)
- {
- return Math.Min(Math.Max(value, 0), ((Class1)instance).MaxQux);
- }
- }
-
- private class Class2 : Class1
- {
- public static readonly PerspexProperty BarProperty =
- PerspexProperty.Register("Bar", "bardefault");
-
- public static readonly PerspexProperty FlobProperty =
- PerspexProperty.Register("Flob");
-
- public static readonly PerspexProperty FredProperty =
- PerspexProperty.Register("Fred");
-
- static Class2()
- {
- FooProperty.OverrideDefaultValue(typeof(Class2), "foooverride");
- }
-
- public Class1 Parent
- {
- get { return (Class1)this.InheritanceParent; }
- set { this.InheritanceParent = value; }
- }
- }
-
- private class ImplictDouble
- {
- public ImplictDouble(double value)
- {
- this.Value = value;
- }
-
- public double Value { get; }
-
- public static implicit operator double(ImplictDouble v)
- {
- return v.Value;
- }
- }
- }
-}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs
new file mode 100644
index 0000000000..eea8f421b3
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs
@@ -0,0 +1,294 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using System;
+ using System.Reactive.Linq;
+ using System.Reactive.Subjects;
+ using Xunit;
+
+ public class PerspexObjectTests_Binding
+ {
+ [Fact]
+ public void Bind_Sets_Current_Value()
+ {
+ Class1 target = new Class1();
+ Class1 source = new Class1();
+
+ source.SetValue(Class1.FooProperty, "initial");
+ target.Bind(Class1.FooProperty, source.GetObservable(Class1.FooProperty));
+
+ Assert.Equal("initial", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void Bind_NonGeneric_Sets_Current_Value()
+ {
+ Class1 target = new Class1();
+ Class1 source = new Class1();
+
+ source.SetValue(Class1.FooProperty, "initial");
+ target.Bind((PerspexProperty)Class1.FooProperty, source.GetObservable(Class1.FooProperty));
+
+ Assert.Equal("initial", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void Bind_Throws_Exception_For_Unregistered_Property()
+ {
+ Class1 target = new Class1();
+
+ Assert.Throws(() =>
+ {
+ target.Bind(Class2.BarProperty, Observable.Return("foo"));
+ });
+ }
+
+ [Fact]
+ public void Bind_Sets_Subsequent_Value()
+ {
+ Class1 target = new Class1();
+ Class1 source = new Class1();
+
+ source.SetValue(Class1.FooProperty, "initial");
+ target.Bind(Class1.FooProperty, source.GetObservable(Class1.FooProperty));
+ source.SetValue(Class1.FooProperty, "subsequent");
+
+ Assert.Equal("subsequent", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void Bind_Throws_Exception_For_Invalid_Value_Type()
+ {
+ Class1 target = new Class1();
+
+ Assert.Throws(() =>
+ {
+ target.Bind((PerspexProperty)Class1.FooProperty, Observable.Return((object)123));
+ });
+ }
+
+ [Fact]
+ public void Two_Way_Binding_Works()
+ {
+ Class1 obj1 = new Class1();
+ Class1 obj2 = new Class1();
+
+ obj1.SetValue(Class1.FooProperty, "initial1");
+ obj2.SetValue(Class1.FooProperty, "initial2");
+
+ obj1.Bind(Class1.FooProperty, obj2.GetObservable(Class1.FooProperty));
+ obj2.Bind(Class1.FooProperty, obj1.GetObservable(Class1.FooProperty));
+
+ Assert.Equal("initial2", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("initial2", obj2.GetValue(Class1.FooProperty));
+
+ obj1.SetValue(Class1.FooProperty, "first");
+
+ Assert.Equal("first", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("first", obj2.GetValue(Class1.FooProperty));
+
+ obj2.SetValue(Class1.FooProperty, "second");
+
+ Assert.Equal("second", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("second", obj2.GetValue(Class1.FooProperty));
+
+ obj1.SetValue(Class1.FooProperty, "third");
+
+ Assert.Equal("third", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("third", obj2.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void Two_Way_Binding_With_Priority_Works()
+ {
+ Class1 obj1 = new Class1();
+ Class1 obj2 = new Class1();
+
+ obj1.SetValue(Class1.FooProperty, "initial1", BindingPriority.Style);
+ obj2.SetValue(Class1.FooProperty, "initial2", BindingPriority.Style);
+
+ obj1.Bind(Class1.FooProperty, obj2.GetObservable(Class1.FooProperty), BindingPriority.Style);
+ obj2.Bind(Class1.FooProperty, obj1.GetObservable(Class1.FooProperty), BindingPriority.Style);
+
+ Assert.Equal("initial2", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("initial2", obj2.GetValue(Class1.FooProperty));
+
+ obj1.SetValue(Class1.FooProperty, "first", BindingPriority.Style);
+
+ Assert.Equal("first", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("first", obj2.GetValue(Class1.FooProperty));
+
+ obj2.SetValue(Class1.FooProperty, "second", BindingPriority.Style);
+
+ Assert.Equal("second", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("second", obj2.GetValue(Class1.FooProperty));
+
+ obj1.SetValue(Class1.FooProperty, "third", BindingPriority.Style);
+
+ Assert.Equal("third", obj1.GetValue(Class1.FooProperty));
+ Assert.Equal("third", obj2.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void BindTwoWay_Gets_Initial_Value_From_Source()
+ {
+ Class1 source = new Class1();
+ Class1 target = new Class1();
+
+ source.SetValue(Class1.FooProperty, "initial");
+ target.BindTwoWay(Class1.FooProperty, source, Class1.FooProperty);
+
+ Assert.Equal("initial", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void BindTwoWay_Updates_Values()
+ {
+ Class1 source = new Class1();
+ Class1 target = new Class1();
+
+ source.SetValue(Class1.FooProperty, "first");
+ target.BindTwoWay(Class1.FooProperty, source, Class1.FooProperty);
+
+ Assert.Equal("first", target.GetValue(Class1.FooProperty));
+ source.SetValue(Class1.FooProperty, "second");
+ Assert.Equal("second", target.GetValue(Class1.FooProperty));
+ target.SetValue(Class1.FooProperty, "third");
+ Assert.Equal("third", source.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void Local_Binding_Overwrites_Local_Value()
+ {
+ var target = new Class1();
+ var binding = new Subject();
+
+ target.Bind(Class1.FooProperty, binding);
+
+ binding.OnNext("first");
+ Assert.Equal("first", target.GetValue(Class1.FooProperty));
+
+ target.SetValue(Class1.FooProperty, "second");
+ Assert.Equal("second", target.GetValue(Class1.FooProperty));
+
+ binding.OnNext("third");
+ Assert.Equal("third", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void StyleBinding_Overrides_Default_Value()
+ {
+ Class1 target = new Class1();
+
+ target.Bind(Class1.FooProperty, this.Single("stylevalue"), BindingPriority.Style);
+
+ Assert.Equal("stylevalue", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void this_Operator_Returns_Value_Property()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.Equal("newvalue", target[Class1.FooProperty]);
+ }
+
+ [Fact]
+ public void this_Operator_Sets_Value_Property()
+ {
+ Class1 target = new Class1();
+
+ target[Class1.FooProperty] = "newvalue";
+
+ Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void this_Operator_Doesnt_Accept_Observable()
+ {
+ Class1 target = new Class1();
+
+ Assert.Throws(() =>
+ {
+ target[Class1.FooProperty] = Observable.Return("newvalue");
+ });
+ }
+
+ [Fact]
+ public void this_Operator_Binds_One_Way()
+ {
+ Class1 target1 = new Class1();
+ Class1 target2 = new Class1();
+ Binding binding = Class1.FooProperty.Bind().WithMode(BindingMode.OneWay);
+
+ target1.SetValue(Class1.FooProperty, "first");
+ target2[binding] = target1[!Class1.FooProperty];
+ target1.SetValue(Class1.FooProperty, "second");
+
+ Assert.Equal("second", target2.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void this_Operator_Binds_Two_Way()
+ {
+ Class1 target1 = new Class1();
+ Class1 target2 = new Class1();
+ Binding binding = Class1.FooProperty.Bind().WithMode(BindingMode.TwoWay);
+
+ target1.SetValue(Class1.FooProperty, "first");
+ target2[binding] = target1[!Class1.FooProperty];
+ Assert.Equal("first", target2.GetValue(Class1.FooProperty));
+ target1.SetValue(Class1.FooProperty, "second");
+ Assert.Equal("second", target2.GetValue(Class1.FooProperty));
+ target2.SetValue(Class1.FooProperty, "third");
+ Assert.Equal("third", target1.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void this_Operator_Binds_One_Time()
+ {
+ Class1 target1 = new Class1();
+ Class1 target2 = new Class1();
+ Binding binding = Class1.FooProperty.Bind().WithMode(BindingMode.OneTime);
+
+ target1.SetValue(Class1.FooProperty, "first");
+ target2[binding] = target1[!Class1.FooProperty];
+ target1.SetValue(Class1.FooProperty, "second");
+
+ Assert.Equal("first", target2.GetValue(Class1.FooProperty));
+ }
+
+ ///
+ /// Returns an observable that returns a single value but does not complete.
+ ///
+ /// The type of the observable.
+ /// The value.
+ /// The observable.
+ private IObservable Single(T value)
+ {
+ return Observable.Never().StartWith(value);
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty FooProperty =
+ PerspexProperty.Register("Foo", "foodefault");
+
+ public static readonly PerspexProperty BazProperty =
+ PerspexProperty.Register("Baz", "bazdefault", true);
+ }
+
+ private class Class2 : Class1
+ {
+ public static readonly PerspexProperty BarProperty =
+ PerspexProperty.Register("Bar", "bardefault");
+ }
+ }
+}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Coercion.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Coercion.cs
new file mode 100644
index 0000000000..bc1784720d
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Coercion.cs
@@ -0,0 +1,59 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using System;
+ using System.Linq;
+ using System.Reactive.Linq;
+ using System.Reactive.Subjects;
+ using Xunit;
+
+ public class PerspexObjectTests_Coercion
+ {
+ [Fact]
+ public void CoerceValue_Causes_Recoercion()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.QuxProperty, 7);
+ Assert.Equal(7, target.GetValue(Class1.QuxProperty));
+ target.MaxQux = 5;
+ target.CoerceValue(Class1.QuxProperty);
+ }
+
+ [Fact]
+ public void SetValue_Causes_Coercion()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.QuxProperty, 5);
+ Assert.Equal(5, target.GetValue(Class1.QuxProperty));
+ target.SetValue(Class1.QuxProperty, -5);
+ Assert.Equal(0, target.GetValue(Class1.QuxProperty));
+ target.SetValue(Class1.QuxProperty, 15);
+ Assert.Equal(10, target.GetValue(Class1.QuxProperty));
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty QuxProperty =
+ PerspexProperty.Register("Qux", coerce: Coerce);
+
+ public Class1()
+ {
+ this.MaxQux = 10;
+ }
+
+ public int MaxQux { get; set; }
+
+ private static int Coerce(PerspexObject instance, int value)
+ {
+ return Math.Min(Math.Max(value, 0), ((Class1)instance).MaxQux);
+ }
+ }
+ }
+}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_GetObservable.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_GetObservable.cs
new file mode 100644
index 0000000000..2fce9f4d36
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_GetObservable.cs
@@ -0,0 +1,85 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using System;
+ using System.Reactive.Linq;
+ using Xunit;
+
+ public class PerspexObjectTests_GetObservable
+ {
+ [Fact]
+ public void GetObservable_Returns_Initial_Value()
+ {
+ Class1 target = new Class1();
+ int raised = 0;
+
+ target.GetObservable(Class1.FooProperty).Subscribe(x =>
+ {
+ if (x == "foodefault")
+ {
+ ++raised;
+ }
+ });
+
+ Assert.Equal(1, raised);
+ }
+
+ [Fact]
+ public void GetObservable_Returns_Property_Change()
+ {
+ Class1 target = new Class1();
+ bool raised = false;
+
+ target.GetObservable(Class1.FooProperty).Subscribe(x => raised = x == "newvalue");
+ raised = false;
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.True(raised);
+ }
+
+ [Fact]
+ public void GetObservable_Returns_Property_Change_Only_For_Correct_Property()
+ {
+ Class2 target = new Class2();
+ bool raised = false;
+
+ target.GetObservable(Class1.FooProperty).Subscribe(x => raised = true);
+ raised = false;
+ target.SetValue(Class2.BarProperty, "newvalue");
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void GetObservable_Dispose_Stops_Property_Changes()
+ {
+ Class1 target = new Class1();
+ bool raised = false;
+
+ target.GetObservable(Class1.FooProperty)
+ .Subscribe(x => raised = true)
+ .Dispose();
+ raised = false;
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.False(raised);
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty FooProperty =
+ PerspexProperty.Register("Foo", "foodefault");
+ }
+
+ private class Class2 : Class1
+ {
+ public static readonly PerspexProperty BarProperty =
+ PerspexProperty.Register("Bar", "bardefault");
+ }
+ }
+}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_GetValue.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_GetValue.cs
new file mode 100644
index 0000000000..288234e673
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_GetValue.cs
@@ -0,0 +1,73 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using Xunit;
+
+ public class PerspexObjectTests_GetValue
+ {
+ [Fact]
+ public void GetValue_Returns_Default_Value()
+ {
+ Class1 target = new Class1();
+
+ Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void GetValue_Returns_Overridden_Default_Value()
+ {
+ Class2 target = new Class2();
+
+ Assert.Equal("foooverride", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void GetValue_Returns_Set_Value()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void GetValue_Returns_Inherited_Value()
+ {
+ Class1 parent = new Class1();
+ Class2 child = new Class2 { Parent = parent };
+
+ parent.SetValue(Class1.BazProperty, "changed");
+
+ Assert.Equal("changed", child.GetValue(Class1.BazProperty));
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty FooProperty =
+ PerspexProperty.Register("Foo", "foodefault");
+
+ public static readonly PerspexProperty BazProperty =
+ PerspexProperty.Register("Baz", "bazdefault", true);
+ }
+
+ private class Class2 : Class1
+ {
+ static Class2()
+ {
+ FooProperty.OverrideDefaultValue(typeof(Class2), "foooverride");
+ }
+
+ public Class1 Parent
+ {
+ get { return (Class1)this.InheritanceParent; }
+ set { this.InheritanceParent = value; }
+ }
+ }
+ }
+}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Inheritance.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Inheritance.cs
new file mode 100644
index 0000000000..e8dfe41d30
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Inheritance.cs
@@ -0,0 +1,104 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using Xunit;
+
+ public class PerspexObjectTests_Inheritance
+ {
+ [Fact]
+ public void GetValue_Returns_Inherited_Value()
+ {
+ Class1 parent = new Class1();
+ Class2 child = new Class2 { Parent = parent };
+
+ parent.SetValue(Class1.BazProperty, "changed");
+
+ Assert.Equal("changed", child.GetValue(Class1.BazProperty));
+ }
+
+ [Fact]
+ public void Setting_InheritanceParent_Raises_PropertyChanged_When_Value_Changed_In_Parent()
+ {
+ bool raised = false;
+
+ Class1 parent = new Class1();
+ parent.SetValue(Class1.BazProperty, "changed");
+
+ Class2 child = new Class2();
+ child.PropertyChanged += (s, e) =>
+ raised = s == child &&
+ e.Property == Class1.BazProperty &&
+ (string)e.OldValue == "bazdefault" &&
+ (string)e.NewValue == "changed";
+
+ child.Parent = parent;
+
+ Assert.True(raised);
+ }
+
+ [Fact]
+ public void Setting_InheritanceParent_Doesnt_Raise_PropertyChanged_When_Local_Value_Set()
+ {
+ bool raised = false;
+
+ Class1 parent = new Class1();
+ parent.SetValue(Class1.BazProperty, "changed");
+
+ Class2 child = new Class2();
+ child.SetValue(Class1.BazProperty, "localvalue");
+ child.PropertyChanged += (s, e) => raised = true;
+
+ child.Parent = parent;
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void Setting_Value_In_InheritanceParent_Raises_PropertyChanged()
+ {
+ bool raised = false;
+
+ Class1 parent = new Class1();
+
+ Class2 child = new Class2();
+ child.PropertyChanged += (s, e) =>
+ raised = s == child &&
+ e.Property == Class1.BazProperty &&
+ (string)e.OldValue == "bazdefault" &&
+ (string)e.NewValue == "changed";
+ child.Parent = parent;
+
+ parent.SetValue(Class1.BazProperty, "changed");
+
+ Assert.True(raised);
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty FooProperty =
+ PerspexProperty.Register("Foo", "foodefault");
+
+ public static readonly PerspexProperty BazProperty =
+ PerspexProperty.Register("Baz", "bazdefault", true);
+ }
+
+ private class Class2 : Class1
+ {
+ static Class2()
+ {
+ FooProperty.OverrideDefaultValue(typeof(Class2), "foooverride");
+ }
+
+ public Class1 Parent
+ {
+ get { return (Class1)this.InheritanceParent; }
+ set { this.InheritanceParent = value; }
+ }
+ }
+ }
+}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs
new file mode 100644
index 0000000000..dcbc1ceedf
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs
@@ -0,0 +1,65 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using System;
+ using System.Linq;
+ using System.Reactive.Linq;
+ using System.Reactive.Subjects;
+ using Xunit;
+
+ public class PerspexObjectTests_Metadata
+ {
+ public PerspexObjectTests_Metadata()
+ {
+ // Ensure properties are registered.
+ PerspexProperty p;
+ p = Class1.FooProperty;
+ p = Class2.BarProperty;
+ }
+
+ [Fact]
+ public void GetProperties_Returns_Registered_Properties()
+ {
+ string[] names = PerspexObject.GetProperties(typeof(Class1)).Select(x => x.Name).ToArray();
+
+ Assert.Equal(new[] { "Foo", "Baz", "Qux" }, names);
+ }
+
+ [Fact]
+ public void GetProperties_Returns_Registered_Properties_For_Base_Types()
+ {
+ string[] names = PerspexObject.GetProperties(typeof(Class2)).Select(x => x.Name).ToArray();
+
+ Assert.Equal(new[] { "Bar", "Flob", "Fred", "Foo", "Baz", "Qux" }, names);
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty FooProperty =
+ PerspexProperty.Register("Foo");
+
+ public static readonly PerspexProperty BazProperty =
+ PerspexProperty.Register("Baz");
+
+ public static readonly PerspexProperty QuxProperty =
+ PerspexProperty.Register("Qux");
+ }
+
+ private class Class2 : Class1
+ {
+ public static readonly PerspexProperty BarProperty =
+ PerspexProperty.Register("Bar");
+
+ public static readonly PerspexProperty FlobProperty =
+ PerspexProperty.Register("Flob");
+
+ public static readonly PerspexProperty FredProperty =
+ PerspexProperty.Register("Fred");
+ }
+ }
+}
diff --git a/Tests/Perspex.Base.UnitTests/PerspexObjectTests_SetValue.cs b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_SetValue.cs
new file mode 100644
index 0000000000..12f4cbb899
--- /dev/null
+++ b/Tests/Perspex.Base.UnitTests/PerspexObjectTests_SetValue.cs
@@ -0,0 +1,212 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Base.UnitTests
+{
+ using System;
+ using System.Linq;
+ using System.Reactive.Linq;
+ using System.Reactive.Subjects;
+ using Xunit;
+
+ public class PerspexObjectTests_SetValue
+ {
+ [Fact]
+ public void ClearValue_Clears_Value()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+ target.ClearValue(Class1.FooProperty);
+
+ Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void SetValue_Sets_Value()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void SetValue_Raises_PropertyChanged()
+ {
+ Class1 target = new Class1();
+ bool raised = false;
+
+ target.PropertyChanged += (s, e) =>
+ {
+ raised = s == target &&
+ e.Property == Class1.FooProperty &&
+ (string)e.OldValue == "foodefault" &&
+ (string)e.NewValue == "newvalue";
+ };
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.True(raised);
+ }
+
+ [Fact]
+ public void SetValue_Doesnt_Raise_PropertyChanged_If_Value_Not_Changed()
+ {
+ Class1 target = new Class1();
+ bool raised = false;
+
+ target.SetValue(Class1.FooProperty, "bar");
+
+ target.PropertyChanged += (s, e) =>
+ {
+ raised = true;
+ };
+
+ target.SetValue(Class1.FooProperty, "bar");
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void SetValue_Doesnt_Raise_PropertyChanged_If_Value_Not_Changed_From_Default()
+ {
+ Class1 target = new Class1();
+ bool raised = false;
+
+ target.PropertyChanged += (s, e) =>
+ {
+ raised = true;
+ };
+
+ target.SetValue(Class1.FooProperty, "foodefault");
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void SetValue_Throws_Exception_For_Unregistered_Property()
+ {
+ Class1 target = new Class1();
+
+ Assert.Throws(() =>
+ {
+ target.SetValue(Class2.BarProperty, "invalid");
+ });
+ }
+
+ [Fact]
+ public void SetValue_Throws_Exception_For_Invalid_Value_Type()
+ {
+ Class1 target = new Class1();
+
+ Assert.Throws(() =>
+ {
+ target.SetValue(Class1.FooProperty, 123);
+ });
+ }
+
+ [Fact]
+ public void SetValue_Of_Integer_On_Double_Property_Works()
+ {
+ Class2 target = new Class2();
+
+ target.SetValue((PerspexProperty)Class2.FlobProperty, 4);
+
+ var value = target.GetValue(Class2.FlobProperty);
+ Assert.IsType(value);
+ Assert.Equal(4, value);
+ }
+
+ [Fact]
+ public void SetValue_Respects_Implicit_Conversions()
+ {
+ Class2 target = new Class2();
+
+ target.SetValue((PerspexProperty)Class2.FlobProperty, new ImplictDouble(4));
+
+ var value = target.GetValue(Class2.FlobProperty);
+ Assert.IsType(value);
+ Assert.Equal(4, value);
+ }
+
+ [Fact]
+ public void SetValue_Can_Convert_To_Nullable()
+ {
+ Class2 target = new Class2();
+
+ target.SetValue((PerspexProperty)Class2.FredProperty, 4.0);
+
+ var value = target.GetValue(Class2.FredProperty);
+ Assert.IsType(value);
+ Assert.Equal(4, value);
+ }
+
+ [Fact]
+ public void SetValue_Respects_Priority()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "one", BindingPriority.TemplatedParent);
+ Assert.Equal("one", target.GetValue(Class1.FooProperty));
+ target.SetValue(Class1.FooProperty, "two", BindingPriority.Style);
+ Assert.Equal("one", target.GetValue(Class1.FooProperty));
+ target.SetValue(Class1.FooProperty, "three", BindingPriority.StyleTrigger);
+ Assert.Equal("three", target.GetValue(Class1.FooProperty));
+ }
+
+ [Fact]
+ public void Setting_UnsetValue_Reverts_To_Default_Value()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+ target.SetValue(Class1.FooProperty, PerspexProperty.UnsetValue);
+
+ Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
+ }
+
+ private class Class1 : PerspexObject
+ {
+ public static readonly PerspexProperty FooProperty =
+ PerspexProperty.Register("Foo", "foodefault");
+ }
+
+ private class Class2 : Class1
+ {
+ public static readonly PerspexProperty BarProperty =
+ PerspexProperty.Register("Bar", "bardefault");
+
+ public static readonly PerspexProperty FlobProperty =
+ PerspexProperty.Register("Flob");
+
+ public static readonly PerspexProperty FredProperty =
+ PerspexProperty.Register("Fred");
+
+ public Class1 Parent
+ {
+ get { return (Class1)this.InheritanceParent; }
+ set { this.InheritanceParent = value; }
+ }
+ }
+
+ private class ImplictDouble
+ {
+ public ImplictDouble(double value)
+ {
+ this.Value = value;
+ }
+
+ public double Value { get; }
+
+ public static implicit operator double (ImplictDouble v)
+ {
+ return v.Value;
+ }
+ }
+ }
+}