public void When_Modified_From_Callback_And_TwoWay() { var dp1 = new MyDP(); var dp2 = new MyDP(); var binding = new Binding { Source = dp1, Path = new PropertyPath(nameof(MyDP.MyInt)), Mode = BindingMode.TwoWay }; BindingOperations.SetBinding(dp2, MyDP.MyIntProperty, binding); var callbackCount = 0; dp1.RegisterPropertyChangedCallback(MyDP.MyIntProperty, OnMyIntChanged); dp2.MyInt = 11; Assert.AreEqual(42, dp1.MyInt); Assert.AreEqual(11, dp2.MyInt); Assert.AreEqual(2, callbackCount); void OnMyIntChanged(DependencyObject sender, DependencyProperty dpInner) { callbackCount++; (sender as MyDP).MyInt = 42; } }
public void When_TwoWay_And_ConvertBack() { var dp1 = new MyDP(); var dp2 = new MyDP(); var conv = new IncrementConverter(); var binding = new Binding { Source = dp1, Path = new PropertyPath(nameof(MyDP.MyInt)), Mode = BindingMode.TwoWay, Converter = conv }; BindingOperations.SetBinding(dp2, MyDP.MyIntProperty, binding); Assert.AreEqual(1, dp2.MyInt); Assert.AreEqual(1, conv.ConvertCount); Assert.AreEqual(0, conv.ConvertBackCount); dp2.MyInt = 7; Assert.AreEqual(dp2.MyInt, 7); Assert.AreEqual(dp1.MyInt, 8); Assert.AreEqual(1, conv.ConvertCount); Assert.AreEqual(1, conv.ConvertBackCount); dp1.MyInt = 19; Assert.AreEqual(19, dp1.MyInt); Assert.AreEqual(20, dp2.MyInt); Assert.AreEqual(2, conv.ConvertCount); Assert.AreEqual(1, conv.ConvertBackCount); }
public void When_TwoWay_And_ConvertBack_Normal_Binding() { var dp1 = new MyDP(); var dp2 = new MyDP(); var conv = new StringToDoubleConverter(); var binding = new Binding { Source = dp1, Path = new PropertyPath(nameof(MyDP.MyDouble)), Mode = BindingMode.TwoWay, Converter = conv }; BindingOperations.SetBinding(dp2, MyDP.MyStringProperty, binding); Assert.AreEqual("¤0.00", dp2.MyString); Assert.AreEqual(1, conv.ConvertCount); Assert.AreEqual(0, conv.ConvertBackCount); dp2.MyString = "42"; // For normal bindings, the source update through the converter // is ignored. Therefore, only the ConvertBack method is invoked as // the UpdateSource method is ignored because a two-way binding is // in progress. This behavior is different with x:Bind. Assert.AreEqual("42", dp2.MyString); Assert.AreEqual(42, dp1.MyDouble); Assert.AreEqual(1, conv.ConvertCount); Assert.AreEqual(1, conv.ConvertBackCount); }
public void When_Modified_From_Callback() { var dp = new MyDP(); var callbackCount = 0; dp.RegisterPropertyChangedCallback(MyDP.MyIntProperty, OnMyIntChanged); dp.MyInt = 11; Assert.AreEqual(42, dp.MyInt); Assert.AreEqual(2, callbackCount); void OnMyIntChanged(DependencyObject sender, DependencyProperty dpInner) { callbackCount++; (sender as MyDP).MyInt = 42; } }
public void When_TwoWay_And_ConvertBack_Normal_xBind() { var dp1 = new MyDP(); var dp2 = new MyDP(); var conv = new StringToDoubleConverter(); var binding = new Binding { Path = new PropertyPath(nameof(MyDP.MyDouble)), Mode = BindingMode.TwoWay, Converter = conv, CompiledSource = dp1, }; BindingOperations.SetBinding(dp2, MyDP.MyStringProperty, binding); dp2.ApplyXBind(); Assert.AreEqual("¤0.00", dp2.MyString); Assert.AreEqual(1, conv.ConvertCount); Assert.AreEqual(0, conv.ConvertBackCount); dp2.MyString = "42"; // For x:Bind, the source update through the converter raises // a property change, which is in turn sent back to the target // after another Convert invocation. // // There is no loop happening because the binding engine is ignoring // the UpdateSource invocation as a two-way binding is still happening. // // This behavior is different with a normal binding. Assert.AreEqual("¤42.00", dp2.MyString); Assert.AreEqual(42, dp1.MyDouble); Assert.AreEqual(2, conv.ConvertCount); Assert.AreEqual(1, conv.ConvertBackCount); }