diff --git a/Perspex.UnitTests/PerspexObjectTests.cs b/Perspex.UnitTests/PerspexObjectTests.cs
index 51a9720062..ebd5b14636 100644
--- a/Perspex.UnitTests/PerspexObjectTests.cs
+++ b/Perspex.UnitTests/PerspexObjectTests.cs
@@ -353,6 +353,37 @@ namespace Perspex.UnitTests
target.Bind((PerspexProperty)Class1.FooProperty, Observable.Return((object)123));
}
+ [TestMethod]
+ 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.AreEqual("initial", target.GetValue(Class1.FooProperty));
+ }
+
+ [TestMethod]
+ public void BindTwoWay_Updates_Values()
+ {
+ Class1 source = new Class1();
+ Class1 target = new Class1();
+
+ System.Diagnostics.Debug.WriteLine("source: " + source.GetHashCode());
+ System.Diagnostics.Debug.WriteLine("target: " + target.GetHashCode());
+
+ source.SetValue(Class1.FooProperty, "first");
+ target.BindTwoWay(Class1.FooProperty, source, Class1.FooProperty);
+
+ Assert.AreEqual("first", target.GetValue(Class1.FooProperty));
+ source.SetValue(Class1.FooProperty, "second");
+ Assert.AreEqual("second", target.GetValue(Class1.FooProperty));
+ target.SetValue(Class1.FooProperty, "third");
+ Assert.AreEqual("third", source.GetValue(Class1.FooProperty));
+ }
+
[TestMethod]
public void Setting_UnsetValue_Reverts_To_Default_Value()
{
@@ -385,6 +416,79 @@ namespace Perspex.UnitTests
Assert.AreEqual("newvalue", target.GetValue(Class1.FooProperty));
}
+ [TestMethod]
+ public void this_Operator_Returns_Value_Property()
+ {
+ Class1 target = new Class1();
+
+ target.SetValue(Class1.FooProperty, "newvalue");
+
+ Assert.AreEqual("newvalue", target[Class1.FooProperty]);
+ }
+
+ [TestMethod]
+ public void this_Operator_Sets_Value_Property()
+ {
+ Class1 target = new Class1();
+
+ target[Class1.FooProperty] = "newvalue";
+
+ Assert.AreEqual("newvalue", target.GetValue(Class1.FooProperty));
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void this_Operator_Doesnt_Accept_Observable()
+ {
+ Class1 target = new Class1();
+
+ target[Class1.FooProperty] = Observable.Return("newvalue");
+ }
+
+ [TestMethod]
+ 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.AreEqual("second", target2.GetValue(Class1.FooProperty));
+ }
+
+ [TestMethod]
+ 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.AreEqual("first", target2.GetValue(Class1.FooProperty));
+ target1.SetValue(Class1.FooProperty, "second");
+ Assert.AreEqual("second", target2.GetValue(Class1.FooProperty));
+ target2.SetValue(Class1.FooProperty, "third");
+ Assert.AreEqual("third", target1.GetValue(Class1.FooProperty));
+ }
+
+ [TestMethod]
+ 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.AreEqual("first", target2.GetValue(Class1.FooProperty));
+ }
+
///
/// Returns an observable that returns a single value but does not complete.
///
diff --git a/Perspex.UnitTests/PerspexPropertyTests.cs b/Perspex.UnitTests/PerspexPropertyTests.cs
index 76e4f5873c..c874751757 100644
--- a/Perspex.UnitTests/PerspexPropertyTests.cs
+++ b/Perspex.UnitTests/PerspexPropertyTests.cs
@@ -19,7 +19,8 @@ namespace Perspex.UnitTests
"test",
typeof(Class1),
"Foo",
- false);
+ false,
+ BindingMode.OneWay);
Assert.AreEqual("test", target.Name);
Assert.AreEqual(typeof(string), target.PropertyType);
@@ -34,7 +35,8 @@ namespace Perspex.UnitTests
"test",
typeof(Class1),
"Foo",
- false);
+ false,
+ BindingMode.OneWay);
Assert.AreEqual("Foo", target.GetDefaultValue());
}
@@ -46,7 +48,8 @@ namespace Perspex.UnitTests
"test",
typeof(Class1),
"Foo",
- false);
+ false,
+ BindingMode.OneWay);
Assert.AreEqual("Foo", target.GetDefaultValue());
}
@@ -58,7 +61,8 @@ namespace Perspex.UnitTests
"test",
typeof(Class3),
"Foo",
- false);
+ false,
+ BindingMode.OneWay);
Assert.AreEqual("Foo", target.GetDefaultValue());
}
@@ -70,7 +74,8 @@ namespace Perspex.UnitTests
"test",
typeof(Class1),
"Foo",
- false);
+ false,
+ BindingMode.OneWay);
target.OverrideDefaultValue(typeof(Class2), "Bar");
diff --git a/Perspex/Binding.cs b/Perspex/Binding.cs
new file mode 100644
index 0000000000..be39daf060
--- /dev/null
+++ b/Perspex/Binding.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Perspex
+{
+ public enum BindingMode
+ {
+ Default,
+ OneWay,
+ TwoWay,
+ OneTime,
+ OneWayToSource,
+ }
+
+ public struct Binding
+ {
+ public BindingMode Mode
+ {
+ get;
+ set;
+ }
+
+ public BindingPriority Priority
+ {
+ get;
+ set;
+ }
+
+ public PerspexProperty Property
+ {
+ get;
+ set;
+ }
+
+ public PerspexObject Source
+ {
+ get;
+ set;
+ }
+
+ public static Binding operator !(Binding binding)
+ {
+ return binding.WithMode(BindingMode.TwoWay);
+ }
+
+ public static Binding operator ~(Binding binding)
+ {
+ return binding.WithMode(BindingMode.TwoWay);
+ }
+
+ public Binding WithMode(BindingMode mode)
+ {
+ this.Mode = mode;
+ return this;
+ }
+
+ public Binding WithPriority(BindingPriority priority)
+ {
+ this.Priority = priority;
+ return this;
+ }
+ }
+}
diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj
index 8b7d8e7802..a35b5aa8e6 100644
--- a/Perspex/Perspex.csproj
+++ b/Perspex/Perspex.csproj
@@ -69,6 +69,7 @@
+
diff --git a/Perspex/PerspexObject.cs b/Perspex/PerspexObject.cs
index 774ba70320..0ea7127f70 100644
--- a/Perspex/PerspexObject.cs
+++ b/Perspex/PerspexObject.cs
@@ -140,13 +140,45 @@ namespace Perspex
}
///
- /// Gets or sets the binding for a .
+ /// Gets or sets a binding for a .
///
- /// The property.
- public IObservable