Esempio n. 1
0
        public void OneTime_Binding_Should_Be_Set_Up()
        {
            var dataContext = new BehaviorSubject<object>(null);
            var expression = new BehaviorSubject<object>(null);
            var target = CreateTarget(dataContext: dataContext);
            var binding = new XamlBinding
            {
                SourcePropertyPath = "Foo",
                BindingMode = BindingMode.OneTime,
            };

            binding.Bind(target.Object, TextBox.TextProperty, expression);

            target.Verify(x => x.SetValue(
                (PerspexProperty)TextBox.TextProperty, 
                null, 
                BindingPriority.LocalValue));
            target.ResetCalls();

            expression.OnNext("foo");
            dataContext.OnNext(1);

            target.Verify(x => x.SetValue(
                (PerspexProperty)TextBox.TextProperty,
                "foo",
                BindingPriority.LocalValue));
        }
Esempio n. 2
0
        public void TwoWay_Binding_Should_Be_Set_Up()
        {
            var target = CreateTarget();
            var binding = new XamlBinding
            {
                SourcePropertyPath = "Foo",
                BindingMode = BindingMode.TwoWay,
            };

            binding.Bind(target.Object, TextBox.TextProperty);

            target.Verify(x => x.BindTwoWay(
                TextBox.TextProperty,
                It.IsAny<ISubject<object>>(),
                BindingPriority.LocalValue));
        }
Esempio n. 3
0
        public void Should_Not_Write_To_Old_DataContext()
        {
            var vm = new OldDataContextViewModel();
            var target = new OldDataContextTest();

            var fooBinding = new XamlBinding
            {
                SourcePropertyPath = "Foo",
                BindingMode = BindingMode.TwoWay,
            };

            var barBinding = new XamlBinding
            {
                SourcePropertyPath = "Bar",
                BindingMode = BindingMode.TwoWay,
            };

            // Bind Foo and Bar to the VM.
            fooBinding.Bind(target, OldDataContextTest.FooProperty);
            barBinding.Bind(target, OldDataContextTest.BarProperty);
            target.DataContext = vm;

            // Make sure the control's Foo and Bar properties are read from the VM
            Assert.Equal(1, target.GetValue(OldDataContextTest.FooProperty));
            Assert.Equal(2, target.GetValue(OldDataContextTest.BarProperty));

            // Set DataContext to null.
            target.DataContext = null;

            // Foo and Bar are no longer bound so they return 0, their default value.
            Assert.Equal(0, target.GetValue(OldDataContextTest.FooProperty));
            Assert.Equal(0, target.GetValue(OldDataContextTest.BarProperty));

            // The problem was here - DataContext is now null, setting Foo to 0. Bar is bound to 
            // Foo so Bar also gets set to 0. However the Bar binding still had a reference to
            // the VM and so vm.Bar was set to 0 erroneously.
            Assert.Equal(1, vm.Foo);
            Assert.Equal(2, vm.Bar);
        }
        private void HandleXamlBindingDefinition(object instance, XamlBindingDefinition def)
        {
            if (_xamlMember.XamlType.UnderlyingType == typeof(XamlBindingDefinition))
            {
                // TODO: This should search base classes.
                var property = instance.GetType().GetTypeInfo().GetDeclaredProperty(_xamlMember.Name);

                if (property == null || !property.CanWrite)
                {
                    throw new InvalidOperationException(
                        $"Cannot assign to '{_xamlMember.Name}' on '{instance.GetType()}");
                }

                property.SetValue(instance, def);
            }
            else
            {
                var perspexObject = instance as PerspexObject;
                var attached = _xamlMember as PerspexAttachableXamlMember;

                if (perspexObject == null)
                {
                    throw new InvalidOperationException(
                        $"Cannot bind to an object of type '{instance.GetType()}");
                }

                PerspexProperty property;
                string propertyName;

                if (attached == null)
                {
                    propertyName = _xamlMember.Name;
                    property = perspexObject.GetRegisteredProperties()
                        .FirstOrDefault(x => x.Name == propertyName);
                }
                else
                {
                    // Ensure the OwnerType's static ctor has been run.
                    RuntimeHelpers.RunClassConstructor(attached.DeclaringType.UnderlyingType.TypeHandle);

                    propertyName = attached.DeclaringType.UnderlyingType.Name + '.' + _xamlMember.Name;

                    property = perspexObject.GetRegisteredProperties()
                        .Where(x => x.IsAttached && x.OwnerType == attached.DeclaringType.UnderlyingType)
                        .FirstOrDefault(x => x.Name == _xamlMember.Name);
                }

                if (property == null)
                {
                    throw new InvalidOperationException(
                        $"Cannot find '{propertyName}' on '{instance.GetType()}");
                }

                var binding = new XamlBinding
                {
                    BindingMode = def.BindingMode,
                    SourcePropertyPath = def.SourcePropertyPath,
                };

                binding.Bind(perspexObject, property);
            }
        }
Esempio n. 5
0
        public void Default_BindingMode_Should_Be_Used()
        {
            var target = CreateTarget(null);
            var binding = new XamlBinding
            {
                SourcePropertyPath = "Foo",
            };

            binding.Bind(target.Object, TextBox.TextProperty);

            // Default for TextBox.Text is two-way.
            target.Verify(x => x.BindTwoWay(
                TextBox.TextProperty,
                It.IsAny<ISubject<object>>(),
                BindingPriority.LocalValue));
        }
Esempio n. 6
0
        public void OneWayToSource_Binding_Should_Be_Set_Up()
        {
            var textObservable = new Mock<IObservable<string>>();
            var expression = new Mock<ISubject<object>>();
            var target = CreateTarget(text: textObservable.Object);
            var binding = new XamlBinding
            {
                SourcePropertyPath = "Foo",
                BindingMode = BindingMode.OneWayToSource,
            };

            binding.Bind(target.Object, TextBox.TextProperty, expression.Object);

            textObservable.Verify(x => x.Subscribe(expression.Object));
        }
Esempio n. 7
0
        public void DataContext_Binding_Should_Use_Parent_DataContext()
        {
            var parentDataContext = Mock.Of<IHeadered>(x => x.Header == (object)"Foo");

            var parent = new Decorator
            {
                Child = new Control(),
                DataContext = parentDataContext,
            };

            var binding = new XamlBinding
            {
                SourcePropertyPath = "Header",
            };

            binding.Bind(parent.Child, Control.DataContextProperty);

            Assert.Equal("Foo", parent.Child.DataContext);

            parentDataContext = Mock.Of<IHeadered>(x => x.Header == (object)"Bar");
            parent.DataContext = parentDataContext;
            Assert.Equal("Bar", parent.Child.DataContext);
        }
        public void Should_Not_Write_To_Old_DataContext()
        {
            var vm = new OldDataContextViewModel();
            var target = new TestSelector();

            var itemsBinding = new XamlBinding
            {
                SourcePropertyPath = "Items",
                BindingMode = BindingMode.OneWay,
            };

            var selectedItemsBinding = new XamlBinding
            {
                SourcePropertyPath = "SelectedItems",
                BindingMode = BindingMode.OneWay,
            };

            // Bind Items and SelectedItems to the VM.
            itemsBinding.Bind(target, TestSelector.ItemsProperty);
            selectedItemsBinding.Bind(target, TestSelector.SelectedItemsProperty);

            // Set DataContext and SelectedIndex
            target.DataContext = vm;
            target.SelectedIndex = 1;

            // Make sure SelectedItems are written back to VM.
            Assert.Equal(new[] { "bar" }, vm.SelectedItems);

            // Clear DataContext and ensure that SelectedItems is still set in the VM.
            target.DataContext = null;
            Assert.Equal(new[] { "bar" }, vm.SelectedItems);
        }