1411 строки
40 KiB
C#
1411 строки
40 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using NUnit.Framework;
|
|
using Xamarin.Forms.Internals;
|
|
|
|
namespace Xamarin.Forms.Core.UnitTests
|
|
{
|
|
[TypeConverter (typeof(ToBarConverter))]
|
|
internal class Bar
|
|
{
|
|
|
|
}
|
|
|
|
internal class Baz
|
|
{
|
|
|
|
}
|
|
|
|
internal class MockBindable
|
|
: VisualElement
|
|
{
|
|
public static readonly BindableProperty TextProperty = BindableProperty.Create<MockBindable, string> (
|
|
b => b.Text, "default", BindingMode.TwoWay);
|
|
|
|
public string Text
|
|
{
|
|
get { return (string)GetValue (TextProperty); }
|
|
set { SetValue (TextProperty, value); }
|
|
}
|
|
|
|
public string Foo { get; set; }
|
|
|
|
public int TargetInt { get; set; }
|
|
|
|
public static readonly BindableProperty BarProperty =
|
|
BindableProperty.Create<MockBindable, Bar> (w => w.Bar, default(Bar));
|
|
|
|
public Bar Bar {
|
|
get { return (Bar)GetValue (BarProperty); }
|
|
set { SetValue (BarProperty, value); }
|
|
}
|
|
|
|
public static readonly BindableProperty BazProperty =
|
|
BindableProperty.Create<MockBindable, Baz> (w => w.Baz, default(Baz));
|
|
|
|
[TypeConverter (typeof (ToBazConverter))]
|
|
public Baz Baz {
|
|
get { return (Baz)GetValue (BazProperty); }
|
|
set { SetValue (BazProperty, value); }
|
|
}
|
|
|
|
public static readonly BindableProperty QuxProperty =
|
|
BindableProperty.Create<MockBindable, Baz> (w => w.Qux, default(Baz));
|
|
|
|
public Baz Qux {
|
|
get { return (Baz)GetValue (QuxProperty); }
|
|
set { SetValue (QuxProperty, value); }
|
|
}
|
|
}
|
|
|
|
internal class ToBarConverter : TypeConverter
|
|
{
|
|
public override object ConvertFrom (System.Globalization.CultureInfo culture, object value)
|
|
{
|
|
return new Bar ();
|
|
}
|
|
}
|
|
|
|
internal class ToBazConverter : TypeConverter
|
|
{
|
|
public override object ConvertFrom (System.Globalization.CultureInfo culture, object value)
|
|
{
|
|
return new Baz ();
|
|
}
|
|
}
|
|
|
|
[TestFixture]
|
|
public class BindableObjectUnitTests : BaseTestFixture
|
|
{
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
Device.PlatformServices = new MockPlatformServices ();
|
|
}
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
Device.PlatformServices = null;
|
|
}
|
|
|
|
[Test]
|
|
public void BindingContext()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.IsNull (mock.BindingContext);
|
|
|
|
object obj = new object();
|
|
mock.BindingContext = obj;
|
|
Assert.AreSame (obj, mock.BindingContext);
|
|
}
|
|
|
|
[Test]
|
|
public void BindingContextChangedEvent()
|
|
{
|
|
var mock = new MockBindable();
|
|
mock.BindingContextChanged += (sender, args) => Assert.Pass();
|
|
|
|
mock.BindingContext = new object();
|
|
|
|
Assert.Fail ("The BindingContextChanged event was not fired.");
|
|
}
|
|
|
|
[Test]
|
|
public void BindingContextChangedOnce()
|
|
{
|
|
var count = 0;
|
|
|
|
var mock = new MockBindable();
|
|
mock.BindingContextChanged += (sender, args) => ++count;
|
|
|
|
mock.BindingContext = new object();
|
|
Assert.AreEqual(count, 1);
|
|
}
|
|
|
|
[Test]
|
|
public void ParentAndChildBindingContextChanged()
|
|
{
|
|
int parentCount = 0, childCount = 0;
|
|
|
|
var didNotChange = " BindingContext did not change.";
|
|
var changedMoreThanOnce = " BindingContext changed more than once.";
|
|
var changedWhenNoChange = " BindingContext was changed when there was no change in context.";
|
|
|
|
var parent = new MockBindable();
|
|
parent.BindingContextChanged += (sender, args) => { ++parentCount; };
|
|
|
|
var child = new MockBindable();
|
|
child.BindingContextChanged += (sender, args) => { ++childCount; };
|
|
|
|
child.Parent = parent;
|
|
Assert.AreEqual(parentCount, 0, "Parent BindingContext was changed while parenting a child.");
|
|
Assert.AreEqual(childCount, 0, "Child" + changedWhenNoChange);
|
|
|
|
child.BindingContext = new object(); // set manually
|
|
Assert.GreaterOrEqual(childCount, 1, "Child" + didNotChange);
|
|
Assert.AreEqual(childCount, 1, "Child" + changedMoreThanOnce);
|
|
Assert.AreEqual(parentCount, 0, "Parent" + changedWhenNoChange);
|
|
|
|
parent.BindingContext = new object();
|
|
Assert.GreaterOrEqual(parentCount, 1, "Parent" + didNotChange);
|
|
Assert.AreEqual(parentCount, 1, "Parent" + changedMoreThanOnce);
|
|
Assert.AreEqual(childCount, 1, "Child" + changedWhenNoChange);
|
|
|
|
child.BindingContext = new object();
|
|
Assert.GreaterOrEqual(childCount, 2, "Child" + didNotChange);
|
|
Assert.AreEqual(childCount, 2, "Child" + changedMoreThanOnce);
|
|
Assert.AreEqual(parentCount, 1, "Parent" + changedWhenNoChange);
|
|
}
|
|
|
|
[Test]
|
|
public void ParentSetOnNullChildBindingContext()
|
|
{
|
|
var parent = new MockBindable();
|
|
|
|
var child = new MockBindable();
|
|
child.BindingContextChanged += (sender, args) => { Assert.Fail("Child BindingContext was changed when there was no change in context."); };
|
|
|
|
child.Parent = parent; // this should not trigger binding context change on child since there is no change
|
|
parent.BindingContext = new object();
|
|
parent.BindingContext = new object();
|
|
}
|
|
|
|
[Test]
|
|
public void ParentSetOnNonNullChildBindingContext()
|
|
{
|
|
var count = 0;
|
|
|
|
var parent = new MockBindable();
|
|
parent.BindingContextChanged += (sender, args) => { ++count; };
|
|
|
|
var child = new MockBindable();
|
|
child.BindingContextChanged += (sender, args) => { ++count; };
|
|
|
|
child.BindingContext = new object(); // set manually
|
|
Assert.AreEqual(count, 1);
|
|
|
|
child.Parent = parent; // this should not trigger binding context change because child binding was set manually
|
|
Assert.AreEqual(count, 1);
|
|
|
|
parent.BindingContext = new object();
|
|
Assert.AreEqual(count, 2);
|
|
|
|
child.BindingContext = new object();
|
|
Assert.AreEqual(count, 3);
|
|
}
|
|
|
|
[Test]
|
|
[Description ("When the BindingContext changes, any bindings should be immediately applied.")]
|
|
public void BindingContextChangedBindingsApplied()
|
|
{
|
|
var mock = new MockBindable();
|
|
mock.SetBinding (MockBindable.TextProperty, new Binding ("."));
|
|
mock.BindingContext = "Test";
|
|
|
|
Assert.AreEqual ("Test", mock.GetValue (MockBindable.TextProperty));
|
|
|
|
mock.BindingContext = "Testing";
|
|
|
|
Assert.AreEqual ("Testing", mock.GetValue (MockBindable.TextProperty),
|
|
"Bindings were not reapplied to the new binding context");
|
|
}
|
|
|
|
[Test]
|
|
[Description ("When the BindingContext changes, the new context needs to listen for updates.")]
|
|
public void BindingContextChangedBindingsListening()
|
|
{
|
|
var mock = new MockBindable();
|
|
mock.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
|
|
|
|
var vm = new MockViewModel();
|
|
mock.BindingContext = vm;
|
|
|
|
mock.BindingContext = (vm = new MockViewModel());
|
|
|
|
vm.Text = "test";
|
|
|
|
Assert.AreEqual ("test", mock.GetValue (MockBindable.TextProperty),
|
|
"The new ViewModel was not being listened to after being set");
|
|
}
|
|
|
|
[Test]
|
|
[Description ("When an INPC implementer is unset as the BindingContext, its changes shouldn't be listened to any further.")]
|
|
public void BindingContextUnsetStopsListening()
|
|
{
|
|
var mock = new MockBindable();
|
|
mock.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
|
|
|
|
var vm = new MockViewModel();
|
|
mock.BindingContext = vm;
|
|
|
|
mock.BindingContext = null;
|
|
|
|
vm.Text = "test";
|
|
|
|
Assert.IsNull (mock.GetValue (Entry.TextProperty), "ViewModel was still being listened to after set to null");
|
|
}
|
|
|
|
[Test]
|
|
public void PropertyChanging()
|
|
{
|
|
var mock = new MockBindable();
|
|
mock.PropertyChanging += (sender, args) => {
|
|
Assert.AreEqual (MockBindable.TextProperty.PropertyName, args.PropertyName);
|
|
Assert.AreEqual (MockBindable.TextProperty.DefaultValue, mock.GetValue (MockBindable.TextProperty));
|
|
Assert.Pass();
|
|
};
|
|
|
|
mock.SetValue (MockBindable.TextProperty, "foo");
|
|
|
|
Assert.Fail ("The PropertyChanging event was not fired.");
|
|
}
|
|
|
|
[Test]
|
|
public void PropertyChangingSameValue()
|
|
{
|
|
const string value = "foo";
|
|
|
|
var mock = new MockBindable();
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
mock.PropertyChanging += (s,e) => Assert.Fail();
|
|
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
|
|
Assert.Pass();
|
|
}
|
|
|
|
[Test]
|
|
public void PropertyChangingDefaultValue()
|
|
{
|
|
var prop = BindableProperty.Create<MockBindable, string> (w => w.Foo, "DefaultValue");
|
|
|
|
var mock = new MockBindable();
|
|
mock.PropertyChanging += (s,e) => Assert.Fail();
|
|
mock.SetValue (prop, prop.DefaultValue);
|
|
|
|
Assert.Pass();
|
|
}
|
|
|
|
[Test]
|
|
public void PropertyChanged()
|
|
{
|
|
const string value = "foo";
|
|
|
|
var mock = new MockBindable();
|
|
mock.PropertyChanged += (sender, args) => {
|
|
Assert.AreEqual (MockBindable.TextProperty.PropertyName, args.PropertyName);
|
|
Assert.AreEqual (value, mock.GetValue (MockBindable.TextProperty));
|
|
Assert.Pass();
|
|
};
|
|
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
|
|
Assert.Fail ("The PropertyChanged event was not fired.");
|
|
}
|
|
|
|
[Test]
|
|
public void PropertyChangedSameValue()
|
|
{
|
|
const string value = "foo";
|
|
|
|
var mock = new MockBindable();
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
mock.PropertyChanged += (s,e) => Assert.Fail();
|
|
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
|
|
Assert.Pass();
|
|
}
|
|
|
|
[Test]
|
|
public void PropertyChangedDefaultValue()
|
|
{
|
|
var prop = BindableProperty.Create<MockBindable, string> (w => w.Foo, "DefaultValue");
|
|
|
|
var mock = new MockBindable();
|
|
mock.PropertyChanged += (s,e) => Assert.Fail();
|
|
|
|
mock.SetValue (prop, prop.DefaultValue);
|
|
|
|
Assert.Pass();
|
|
}
|
|
|
|
[Test]
|
|
public void GetSetValue()
|
|
{
|
|
const string value = "foo";
|
|
var mock = new MockBindable();
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
|
|
Assert.AreEqual (value, mock.GetValue (MockBindable.TextProperty));
|
|
}
|
|
|
|
[Test]
|
|
public void GetValueDefault()
|
|
{
|
|
var nulldefault = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
|
|
TestGetValueDefault (nulldefault);
|
|
|
|
var foodefault = BindableProperty.Create<MockBindable, string> (w => w.Foo, "Foo");
|
|
TestGetValueDefault (foodefault);
|
|
}
|
|
|
|
void TestGetValueDefault (BindableProperty property)
|
|
{
|
|
var mock = new MockBindable();
|
|
object value = mock.GetValue (property);
|
|
Assert.AreEqual (property.DefaultValue, value);
|
|
}
|
|
|
|
[Test]
|
|
public void SetValueInvalid()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.Throws<ArgumentNullException> (() => mock.SetValue ((BindableProperty)null, "null"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetValueInvalid()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.Throws<ArgumentNullException> (() => mock.GetValue (null));
|
|
}
|
|
|
|
[Test]
|
|
public void ClearValueInvalid()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.Throws<ArgumentNullException> (() => mock.ClearValue ((BindableProperty)null));
|
|
}
|
|
|
|
[Test]
|
|
public void ClearValue()
|
|
{
|
|
const string value = "foo";
|
|
var mock = new MockBindable();
|
|
mock.SetValue (MockBindable.TextProperty, value);
|
|
Assert.AreEqual (value, mock.GetValue (MockBindable.TextProperty));
|
|
|
|
mock.ClearValue (MockBindable.TextProperty);
|
|
TestGetValueDefault (MockBindable.TextProperty);
|
|
}
|
|
|
|
[Test]
|
|
public void ClearValueTriggersINPC ()
|
|
{
|
|
var bindable = new MockBindable ();
|
|
bool changingfired = false;
|
|
bool changedfired = false;
|
|
bool changingdelegatefired = false;
|
|
bool changeddelegatefired = false;
|
|
var property = BindableProperty.Create ("Foo", typeof(string), typeof(MockBindable), "foo",
|
|
propertyChanged: (b, o, n) => changeddelegatefired = true,
|
|
propertyChanging: (b, o, n) => changingdelegatefired = true
|
|
);
|
|
bindable.PropertyChanged += (sender, e) => { changedfired |= e.PropertyName == "Foo"; };
|
|
bindable.PropertyChanging += (sender, e) => { changingfired |= e.PropertyName == "Foo"; };
|
|
|
|
bindable.SetValue (property, "foobar");
|
|
changingfired = changedfired = changeddelegatefired = changingdelegatefired = false;
|
|
|
|
bindable.ClearValue (property);
|
|
Assert.True (changingfired);
|
|
Assert.True (changedfired);
|
|
Assert.True (changingdelegatefired);
|
|
Assert.True (changeddelegatefired);
|
|
}
|
|
|
|
[Test]
|
|
public void ClearValueDoesNotTriggersINPCOnSameValues ()
|
|
{
|
|
var bindable = new MockBindable ();
|
|
bool changingfired = false;
|
|
bool changedfired = false;
|
|
bool changingdelegatefired = false;
|
|
bool changeddelegatefired = false;
|
|
var property = BindableProperty.Create ("Foo", typeof(string), typeof(MockBindable), "foo",
|
|
propertyChanged: (b, o, n) => changeddelegatefired = true,
|
|
propertyChanging: (b, o, n) => changingdelegatefired = true
|
|
);
|
|
bindable.PropertyChanged += (sender, e) => { changedfired |= e.PropertyName == "Foo"; };
|
|
bindable.PropertyChanging += (sender, e) => { changingfired |= e.PropertyName == "Foo"; };
|
|
|
|
bindable.SetValue (property, "foobar");
|
|
bindable.SetValue (property, "foo");
|
|
changingfired = changedfired = changeddelegatefired = changingdelegatefired = false;
|
|
|
|
bindable.ClearValue (property);
|
|
Assert.False (changingfired);
|
|
Assert.False (changedfired);
|
|
Assert.False (changingdelegatefired);
|
|
Assert.False (changeddelegatefired);
|
|
}
|
|
|
|
[Test]
|
|
public void SetBindingInvalid()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.Throws<ArgumentNullException> (() => mock.SetBinding (null, new Binding (".")));
|
|
Assert.Throws<ArgumentNullException> (() => mock.SetBinding (MockBindable.TextProperty, null));
|
|
}
|
|
|
|
[Test]
|
|
public void RemoveUnaddedBinding()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.That (() => mock.RemoveBinding (MockBindable.TextProperty), Throws.Nothing);
|
|
}
|
|
|
|
[Test]
|
|
public void RemoveBindingInvalid()
|
|
{
|
|
var mock = new MockBindable();
|
|
Assert.Throws<ArgumentNullException> (() => mock.RemoveBinding (null));
|
|
}
|
|
|
|
[Test]
|
|
public void RemovedBindingDoesNotUpdate()
|
|
{
|
|
const string newvalue = "New Value";
|
|
var viewmodel = new MockViewModel {
|
|
Text = "Foo"
|
|
};
|
|
|
|
var binding = new Binding ("Text");
|
|
|
|
var bindable = new MockBindable();
|
|
bindable.BindingContext = viewmodel;
|
|
bindable.SetBinding (MockBindable.TextProperty, binding);
|
|
|
|
string original = (string)bindable.GetValue (MockBindable.TextProperty);
|
|
|
|
bindable.RemoveBinding (MockBindable.TextProperty);
|
|
|
|
viewmodel.Text = newvalue;
|
|
Assert.AreEqual (original, bindable.GetValue (MockBindable.TextProperty),
|
|
"Property updated from a removed binding");
|
|
}
|
|
|
|
[Test]
|
|
public void CoerceValue()
|
|
{
|
|
var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null,
|
|
coerceValue: (bo, o) => o.ToUpper());
|
|
|
|
const string value = "value";
|
|
var mock = new MockBindable();
|
|
mock.SetValue (property, value);
|
|
Assert.AreEqual (value.ToUpper(), mock.GetValue (property));
|
|
}
|
|
|
|
[Test]
|
|
public void ValidateValue()
|
|
{
|
|
var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null,
|
|
validateValue: (b, v) => false);
|
|
|
|
var mock = new MockBindable();
|
|
Assert.Throws<ArgumentException> (() => mock.SetValue (property, null));
|
|
}
|
|
|
|
[Test]
|
|
public void BindablePropertyChanged()
|
|
{
|
|
bool changed = false;
|
|
|
|
string oldv = "bar";
|
|
string newv = "foo";
|
|
|
|
var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, oldv,
|
|
propertyChanged: (b, ov, nv) => {
|
|
Assert.AreSame (oldv, ov);
|
|
Assert.AreSame (newv, nv);
|
|
changed = true;
|
|
});
|
|
|
|
var mock = new MockBindable();
|
|
mock.SetValue (property, newv);
|
|
|
|
Assert.IsTrue (changed, "PropertyChanged was not called");
|
|
}
|
|
|
|
[Test]
|
|
public void RecursiveChange ()
|
|
{
|
|
bool changedA1 = false, changedA2 = false, changedB1 = false, changedB2 = false;
|
|
|
|
var mock = new MockBindable ();
|
|
mock.PropertyChanged += (sender, args) => {
|
|
if (!changedA1) {
|
|
Assert.AreEqual ("1", mock.GetValue (MockBindable.TextProperty));
|
|
Assert.IsFalse (changedA2);
|
|
Assert.IsFalse (changedB1);
|
|
Assert.IsFalse (changedB2);
|
|
mock.SetValue (MockBindable.TextProperty, "2");
|
|
changedA1 = true;
|
|
} else {
|
|
Assert.AreEqual ("2", mock.GetValue (MockBindable.TextProperty));
|
|
Assert.IsFalse (changedA2);
|
|
Assert.IsTrue (changedB1);
|
|
Assert.IsFalse (changedB2);
|
|
changedA2 = true;
|
|
}
|
|
};
|
|
mock.PropertyChanged += (sender, args) => {
|
|
if (!changedB1) {
|
|
Assert.AreEqual ("1", mock.GetValue (MockBindable.TextProperty));
|
|
Assert.IsTrue (changedA1);
|
|
Assert.IsFalse (changedA2);
|
|
Assert.IsFalse (changedB2);
|
|
changedB1 = true;
|
|
} else {
|
|
Assert.AreEqual ("2", mock.GetValue (MockBindable.TextProperty));
|
|
Assert.IsTrue (changedA1);
|
|
Assert.IsTrue (changedA2);
|
|
Assert.IsFalse (changedB2);
|
|
changedB2 = true;
|
|
}
|
|
};
|
|
mock.SetValue (MockBindable.TextProperty, "1");
|
|
Assert.AreEqual ("2", mock.GetValue (MockBindable.TextProperty));
|
|
Assert.IsTrue (changedA1);
|
|
Assert.IsTrue (changedA2);
|
|
Assert.IsTrue (changedB1);
|
|
Assert.IsTrue (changedB2);
|
|
}
|
|
|
|
[Test]
|
|
public void RaiseOnEqual()
|
|
{
|
|
string foo = "foo";
|
|
var mock = new MockBindable();
|
|
mock.SetValue (MockBindable.TextProperty, foo);
|
|
|
|
bool changing = false;
|
|
mock.PropertyChanging += (o, e) => {
|
|
Assert.That (e.PropertyName, Is.EqualTo (MockBindable.TextProperty.PropertyName));
|
|
changing = true;
|
|
};
|
|
|
|
bool changed = true;
|
|
mock.PropertyChanged += (o, e) => {
|
|
Assert.That (e.PropertyName, Is.EqualTo (MockBindable.TextProperty.PropertyName));
|
|
changed = true;
|
|
};
|
|
|
|
mock.SetValueCore (MockBindable.TextProperty, foo,
|
|
SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource | SetValueFlags.RaiseOnEqual);
|
|
|
|
Assert.That (changing, Is.True, "PropertyChanging event did not fire");
|
|
Assert.That (changed, Is.True, "PropertyChanged event did not fire");
|
|
}
|
|
|
|
[Test]
|
|
public void BindingContextGetter ()
|
|
{
|
|
var label = new Label ();
|
|
var view = new StackLayout { Children = {label} };
|
|
|
|
view.BindingContext = new {item0 = "Foo", item1 = "Bar"};
|
|
label.SetBinding (BindableObject.BindingContextProperty, "item0");
|
|
label.SetBinding (Label.TextProperty, Binding.SelfPath);
|
|
|
|
Assert.AreSame (label.BindingContext, label.GetValue (BindableObject.BindingContextProperty));
|
|
}
|
|
|
|
[Test]
|
|
public void BoundBindingContextUpdate ()
|
|
{
|
|
var label = new Label ();
|
|
var view = new StackLayout { Children = {label} };
|
|
var vm = new MockViewModel { Text = "FooBar" };
|
|
|
|
view.BindingContext = vm;
|
|
label.SetBinding (BindableObject.BindingContextProperty, "Text");
|
|
label.SetBinding (Label.TextProperty, Binding.SelfPath);
|
|
|
|
Assert.AreEqual ("FooBar", label.BindingContext);
|
|
|
|
vm.Text = "Baz";
|
|
Assert.AreEqual ("Baz", label.BindingContext);
|
|
}
|
|
|
|
[Test]
|
|
public void BoundBindingContextChange ()
|
|
{
|
|
var label = new Label ();
|
|
var view = new StackLayout { Children = {label} };
|
|
|
|
view.BindingContext = new MockViewModel { Text = "FooBar" };;
|
|
label.SetBinding (BindableObject.BindingContextProperty, "Text");
|
|
label.SetBinding (Label.TextProperty, Binding.SelfPath);
|
|
|
|
Assert.AreEqual ("FooBar", label.BindingContext);
|
|
|
|
view.BindingContext = new MockViewModel { Text = "Baz" };;
|
|
Assert.AreEqual ("Baz", label.BindingContext);
|
|
}
|
|
|
|
[Test]
|
|
public void TestReadOnly ()
|
|
{
|
|
var bindablePropertyKey = BindableProperty.CreateReadOnly<MockBindable, string> (w => w.Foo, "DefaultValue");
|
|
var bindableProperty = bindablePropertyKey.BindableProperty;
|
|
|
|
var bindable = new MockBindable ();
|
|
Assert.AreEqual ("DefaultValue", bindable.GetValue (bindableProperty));
|
|
|
|
bindable.SetValue (bindablePropertyKey, "Bar");
|
|
Assert.AreEqual ("Bar", bindable.GetValue (bindableProperty));
|
|
|
|
Assert.Throws<InvalidOperationException> (() => bindable.SetValue (bindableProperty, "Baz"));
|
|
Assert.AreEqual ("Bar", bindable.GetValue (bindableProperty));
|
|
|
|
Assert.Throws<InvalidOperationException> (() => bindable.ClearValue (bindableProperty));
|
|
|
|
bindable.ClearValue (bindablePropertyKey);
|
|
Assert.AreEqual ("DefaultValue", bindable.GetValue (bindableProperty));
|
|
}
|
|
|
|
[Test]
|
|
public void TestBindingTwoWayOnReadOnly ()
|
|
{
|
|
var bindablePropertyKey = BindableProperty.CreateReadOnly<MockBindable, string> (w => w.Foo, "DefaultValue", BindingMode.OneWayToSource);
|
|
var bindableProperty = bindablePropertyKey.BindableProperty;
|
|
|
|
var bindable = new MockBindable ();
|
|
var vm = new MockViewModel ();
|
|
|
|
bindable.SetBinding (bindableProperty, new Binding ("Text", BindingMode.TwoWay));
|
|
Assert.DoesNotThrow (() => bindable.BindingContext = vm);
|
|
|
|
Assert.AreEqual ("DefaultValue", bindable.GetValue (bindableProperty));
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreator ()
|
|
{
|
|
int invoked = 0;
|
|
object defaultValue = new object ();
|
|
var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), defaultValue, defaultValueCreator: o => {
|
|
invoked++;
|
|
return new object ();
|
|
});
|
|
var bindable = new MockBindable ();
|
|
|
|
Assert.AreSame (defaultValue, bindableProperty.DefaultValue);
|
|
var newvalue = bindable.GetValue (bindableProperty);
|
|
Assert.AreNotSame (defaultValue, newvalue);
|
|
Assert.NotNull (newvalue);
|
|
Assert.AreEqual (1, invoked);
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreatorIsInvokedOnlyAtFirstTime ()
|
|
{
|
|
int invoked = 0;
|
|
var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o => {
|
|
invoked++;
|
|
return new object ();
|
|
});
|
|
var bindable = new MockBindable ();
|
|
|
|
var value0 = bindable.GetValue (bindableProperty);
|
|
var value1 = bindable.GetValue (bindableProperty);
|
|
Assert.NotNull (value0);
|
|
Assert.NotNull (value1);
|
|
Assert.AreSame (value0, value1);
|
|
Assert.AreEqual (1, invoked);
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreatorNotSharedAccrossInstances ()
|
|
{
|
|
int invoked = 0;
|
|
var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o=> {
|
|
invoked++;
|
|
return new object ();
|
|
});
|
|
var bindable0 = new MockBindable ();
|
|
var bindable1 = new MockBindable ();
|
|
var value0 = bindable0.GetValue (bindableProperty);
|
|
var value1 = bindable1.GetValue (bindableProperty);
|
|
|
|
Assert.AreNotSame (value0, value1);
|
|
Assert.AreEqual (2, invoked);
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreatorInvokedAfterClearValue ()
|
|
{
|
|
int invoked = 0;
|
|
var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o => {
|
|
invoked++;
|
|
return new object ();
|
|
});
|
|
var bindable = new MockBindable ();
|
|
|
|
Assert.AreEqual (0, invoked);
|
|
|
|
var value0 = bindable.GetValue (bindableProperty);
|
|
Assert.NotNull (value0);
|
|
Assert.AreEqual (1, invoked);
|
|
bindable.ClearValue (bindableProperty);
|
|
|
|
var value1 = bindable.GetValue (bindableProperty);
|
|
Assert.NotNull (value1);
|
|
Assert.AreEqual (2, invoked);
|
|
Assert.AreNotSame (value0, value1);
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreatorOnlyInvokedOnGetValue ()
|
|
{
|
|
int invoked = 0;
|
|
var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o => {
|
|
invoked++;
|
|
return new object ();
|
|
});
|
|
var bindable = new MockBindable ();
|
|
|
|
Assert.AreEqual (0, invoked);
|
|
|
|
var newvalue = bindable.GetValue (bindableProperty);
|
|
Assert.NotNull (newvalue);
|
|
Assert.AreEqual (1, invoked);
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreatorDoesNotTriggerINPC ()
|
|
{
|
|
int invoked = 0;
|
|
int propertychanged = 0;
|
|
int changedfired = 0;
|
|
var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null,
|
|
propertyChanged: (bindable,oldvalue,newvalue) =>{
|
|
propertychanged ++;
|
|
},
|
|
defaultValueCreator: o => {
|
|
invoked++;
|
|
return new object ();
|
|
});
|
|
|
|
var bp = new MockBindable ();
|
|
bp.PropertyChanged += (sender, e) => {
|
|
if (e.PropertyName == "Foo")
|
|
changedfired++;
|
|
};
|
|
var value0 = bp.GetValue (bindableProperty);
|
|
Assert.NotNull (value0);
|
|
Assert.AreEqual (1, invoked);
|
|
Assert.AreEqual (0, propertychanged);
|
|
Assert.AreEqual (0, changedfired);
|
|
|
|
}
|
|
|
|
[Test]
|
|
public void StyleValueIsOverridenByValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetValue (Label.TextProperty, "Foo", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleBindingIsOverridenByValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
|
|
label.BindingContext = new {foo = "Foo"};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleDynResourceIsOverridenByValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetDynamicResource (Label.TextProperty, "foo", true);
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"}
|
|
};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleValueIsOverridenByBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetValue (Label.TextProperty, "Foo", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, "bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleBindingIsOverridenByBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, "bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleDynResourceIsOverridenByBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetDynamicResource (Label.TextProperty, "foo", true);
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, "bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleValueIsOverridenByDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetValue (Label.TextProperty, "Foo", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleBindingIsOverridenByDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleDynResourceIsOverridenByDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetDynamicResource (Label.TextProperty, "foo", true);
|
|
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar");
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void ValueIsPreservedOnStyleValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetValue (Label.TextProperty, "Foo");
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
[Test]
|
|
public void BindingIsPreservedOnStyleValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"));
|
|
label.BindingContext = new {foo = "Foo"};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
[Test]
|
|
public void DynResourceIsPreservedOnStyleValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetDynamicResource (Label.TextProperty, "foo");
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"}
|
|
};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void ValueIsPreservedOnStyleBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetValue (Label.TextProperty, "Foo");
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, new Binding ("bar"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void BindingIsPreservedOnStyleBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"));
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, new Binding ("bar"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void DynResourceIsPreservedOnStyleBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetDynamicResource (Label.TextProperty, "foo");
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, new Binding ("bar"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void ValueIsPreservedOnStyleDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetValue (Label.TextProperty, "Foo");
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void BindingIsPreservedOnStyleDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"));
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void DynResourceIsPreservedOnStyleDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetDynamicResource (Label.TextProperty, "foo");
|
|
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleValueIsOverridenByStyleValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetValue (Label.TextProperty, "Foo", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar", true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleBindingIsOverridenByStyleValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
|
|
label.BindingContext = new {foo = "Foo"};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar", true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleDynResourceIsOverridenByStyleValue ()
|
|
{
|
|
var label = new Label ();
|
|
label.SetDynamicResource (Label.TextProperty, "foo", true);
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"}
|
|
};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetValue (Label.TextProperty, "Bar", true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleValueIsOverridenByStyleBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetValue (Label.TextProperty, "Foo", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, new Binding("bar"), true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleBindingIsOverridenByStyleBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, new Binding("bar"), true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleDynResourceIsOverridenByStyleBinding ()
|
|
{
|
|
var label = new Label ();
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetDynamicResource (Label.TextProperty, "foo", true);
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
};
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetBinding (Label.TextProperty, new Binding("bar"), true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleValueIsOverridenByStyleDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetValue (Label.TextProperty, "Foo", true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar", true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleBindingIsOverridenByStyleDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar", true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void StyleDynResourceIsOverridenByStyleDynResource ()
|
|
{
|
|
var label = new Label ();
|
|
label.Resources = new ResourceDictionary {
|
|
{"foo", "Foo"},
|
|
{"bar", "Bar"}
|
|
};
|
|
label.BindingContext = new {foo = "Foo", bar = "Bar"};
|
|
label.SetDynamicResource (Label.TextProperty, "foo", true);
|
|
|
|
Assert.AreEqual ("Foo", label.Text);
|
|
|
|
label.SetDynamicResource (Label.TextProperty, "bar", true);
|
|
Assert.AreEqual ("Bar", label.Text);
|
|
}
|
|
|
|
[Test]
|
|
public void SetValueCoreImplicitelyCastBasicType ()
|
|
{
|
|
var prop = BindableProperty.Create ("Foo", typeof(int), typeof(MockBindable), 0);
|
|
var bindable = new MockBindable ();
|
|
|
|
Assert.DoesNotThrow (() => bindable.SetValue (prop, (object)(short)42));
|
|
Assert.AreEqual (42, bindable.GetValue (prop));
|
|
|
|
bindable.SetValue (prop, (object)(long)-42);
|
|
Assert.AreNotEqual (-42, bindable.GetValue (prop));
|
|
}
|
|
|
|
class CastFromString
|
|
{
|
|
public string Result { get; private set; }
|
|
public static implicit operator CastFromString (string source)
|
|
{
|
|
var o = new CastFromString ();
|
|
o.Result = source;
|
|
return o;
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SetValueCoreInvokesOpImplicitOnPropertyType ()
|
|
{
|
|
var prop = BindableProperty.Create ("Foo", typeof(CastFromString), typeof(MockBindable), null);
|
|
var bindable = new MockBindable ();
|
|
|
|
Assert.Null (bindable.GetValue (prop));
|
|
bindable.SetValue (prop, "foo");
|
|
|
|
Assert.AreEqual ("foo", ((CastFromString)bindable.GetValue (prop)).Result);
|
|
}
|
|
|
|
class CastToString
|
|
{
|
|
string Result { get; set; }
|
|
|
|
public CastToString (string result)
|
|
{
|
|
Result = result;
|
|
}
|
|
|
|
public static implicit operator string (CastToString source)
|
|
{
|
|
return source.Result;
|
|
}
|
|
|
|
public override string ToString ()
|
|
{
|
|
throw new InvalidOperationException ();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SetValueCoreInvokesOpImplicitOnValue ()
|
|
{
|
|
var prop = BindableProperty.Create ("Foo", typeof(string), typeof(MockBindable), null);
|
|
var bindable = new MockBindable ();
|
|
|
|
Assert.Null (bindable.GetValue (prop));
|
|
bindable.SetValue (prop, new CastToString ("foo"));
|
|
|
|
Assert.AreEqual ("foo", bindable.GetValue (prop));
|
|
}
|
|
|
|
[Test]
|
|
public void DefaultValueCreatorCalledForChangeDelegates ()
|
|
{
|
|
int changedOld = -1;
|
|
int changedNew = -1;
|
|
|
|
int changingOld = -1;
|
|
int changingNew = -1;
|
|
var prop = BindableProperty.Create ("Foo", typeof (int), typeof (MockBindable), 0, defaultValueCreator: b => 10,
|
|
propertyChanged: (b, value, newValue) => {
|
|
changedOld = (int) value;
|
|
changedNew = (int) newValue;
|
|
},
|
|
propertyChanging: (b, value, newValue) => {
|
|
changingOld = (int) value;
|
|
changingNew = (int) newValue;
|
|
});
|
|
|
|
var bindable = new MockBindable ();
|
|
|
|
|
|
var defaultValue = (int) bindable.GetValue (prop);
|
|
|
|
Assert.AreEqual (10, defaultValue);
|
|
|
|
bindable.SetValue (prop, 5);
|
|
|
|
bindable.ClearValue (prop);
|
|
|
|
Assert.AreEqual (5, changedOld);
|
|
Assert.AreEqual (5, changingOld);
|
|
Assert.AreEqual (10, changedNew);
|
|
Assert.AreEqual (10, changingNew);
|
|
}
|
|
|
|
[Test]
|
|
public void GetValuesDefaults()
|
|
{
|
|
var prop = BindableProperty.Create ("Foo", typeof(int), typeof(MockBindable), 0);
|
|
var prop1 = BindableProperty.Create ("Foo1", typeof(int), typeof(MockBindable), 1);
|
|
var prop2 = BindableProperty.Create ("Foo2", typeof(int), typeof(MockBindable), 2);
|
|
var bindable = new MockBindable ();
|
|
|
|
|
|
object[] values = bindable.GetValues (prop, prop1, prop2);
|
|
Assert.That (values.Length == 3);
|
|
Assert.That (values[0], Is.EqualTo (0));
|
|
Assert.That (values[1], Is.EqualTo (1));
|
|
Assert.That (values[2], Is.EqualTo (2));
|
|
}
|
|
|
|
[Test]
|
|
public void GetValues()
|
|
{
|
|
var prop = BindableProperty.Create ("Foo", typeof(int), typeof(MockBindable), 0);
|
|
var prop1 = BindableProperty.Create ("Foo1", typeof(int), typeof(MockBindable), 1);
|
|
var prop2 = BindableProperty.Create ("Foo2", typeof(int), typeof(MockBindable), 2);
|
|
var bindable = new MockBindable ();
|
|
bindable.SetValue (prop, 3);
|
|
bindable.SetValue (prop2, 5);
|
|
|
|
|
|
object[] values = bindable.GetValues (prop, prop1, prop2);
|
|
Assert.That (values.Length == 3);
|
|
Assert.That (values[0], Is.EqualTo (3));
|
|
Assert.That (values[1], Is.EqualTo (1));
|
|
Assert.That (values[2], Is.EqualTo (5));
|
|
}
|
|
|
|
class BindingContextConverter
|
|
: IValueConverter
|
|
{
|
|
public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
return new MockViewModel { Text = value + "Converted" };
|
|
}
|
|
|
|
public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
//https://bugzilla.xamarin.com/show_bug.cgi?id=24485
|
|
public void BindingContextBoundThroughConverter()
|
|
{
|
|
var bindable = new MockBindable();
|
|
bindable.BindingContext = "test";
|
|
bindable.SetBinding (BindableObject.BindingContextProperty, new Binding (".", converter: new BindingContextConverter()));
|
|
bindable.SetBinding (MockBindable.TextProperty, "Text");
|
|
|
|
Assert.That (() => bindable.Text, Is.EqualTo ("testConverted"));
|
|
}
|
|
|
|
public class VMLocator
|
|
{
|
|
public event EventHandler Invoked;
|
|
public int Count;
|
|
public object VM {
|
|
get {
|
|
Count++;
|
|
var eh = Invoked;
|
|
if (eh != null)
|
|
eh (this, EventArgs.Empty);
|
|
return new object ();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
//https://bugzilla.xamarin.com/show_bug.cgi?id=27299
|
|
public void BindingOnBindingContextDoesntReapplyBindingContextBinding ()
|
|
{
|
|
var bindable = new MockBindable ();
|
|
var locator = new VMLocator ();
|
|
Assert.AreEqual (0, locator.Count);
|
|
locator.Invoked += (sender, e) => Assert.IsTrue (locator.Count <= 1);
|
|
bindable.SetBinding (BindableObject.BindingContextProperty, new Binding ("VM", source: locator));
|
|
Assert.IsTrue (locator.Count == 1);
|
|
}
|
|
|
|
[Test]
|
|
public void BindingsEditableAfterUnapplied()
|
|
{
|
|
var bindable = new MockBindable();
|
|
|
|
var binding = new Binding (".");
|
|
bindable.SetBinding (MockBindable.TextProperty, binding);
|
|
bindable.BindingContext = "foo";
|
|
|
|
Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
|
|
|
|
bindable.RemoveBinding (MockBindable.TextProperty);
|
|
|
|
Assert.That (() => binding.Path = "foo", Throws.Nothing);
|
|
}
|
|
|
|
[Test]
|
|
// https://bugzilla.xamarin.com/show_bug.cgi?id=24054
|
|
public void BindingsAppliedUnappliedWithNullContext()
|
|
{
|
|
var bindable = new MockBindable();
|
|
|
|
var binding = new Binding (".");
|
|
bindable.SetBinding (MockBindable.TextProperty, binding);
|
|
bindable.BindingContext = "foo";
|
|
|
|
Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
|
|
|
|
bindable.BindingContext = null;
|
|
|
|
Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
|
|
|
|
bindable.BindingContext = "bar";
|
|
|
|
Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
|
|
|
|
bindable.RemoveBinding (MockBindable.TextProperty);
|
|
|
|
Assert.That (() => binding.Path = "Foo", Throws.Nothing);
|
|
}
|
|
}
|
|
} |