예제 #1
0
        public void NestedCollectionAbsolutePathTest()
        {
            /*Arrange*/

            //create a parent binding.
            /*Arrange*/
            Binding.BindingDef parent = new Binding.BindingDef(new WebformControl(new TextBox()), "", new Options {
                Path = ""
            }, controlService);
            string rawPath = "ViewModelID";

            BindingPath path      = new BindingPath(rawPath, parent.SourceExpression, PathMode.Absolute);
            var         viewModel = new { ViewModelID = "viewmodel1" };

            /*Act*/
            SourceProperty sourceProperty = path.ResolveAsSource(viewModel);

            /*Assert*/
            Assert.IsNotNull(sourceProperty);
            Assert.IsNotNull(sourceProperty.Descriptor);
            Assert.IsNotNull(sourceProperty.OwningInstance);
            Assert.IsNotNull(sourceProperty.Value);
            Assert.AreEqual("ViewModelID", sourceProperty.Descriptor.Name);
            Assert.AreEqual(viewModel, sourceProperty.OwningInstance);
            Assert.AreEqual(viewModel.ViewModelID, sourceProperty.Value);
        }
예제 #2
0
        public void VerifyTextboxTextProgrammaticBindCreatesCorrectBindingObject()
        {
            /*Arrange*/
            //We expect at least one call
            this.viewModel.Expect(vm => vm.EmployeeName).Return("Sam Shiles").Repeat.Once();

            TextBox tb      = new TextBox();
            Options options = new Options {
                Path = "EmployeeName"
            };

            /*Act*/
            object resolvedValue = this.binder.ExecuteBind(new WebformControl(tb), options, "Text");

            /*Assert*/
            //Assert on the binding collection to make sure that the binding has been created successfully
            Assert.IsNotNull(collection);
            Assert.AreEqual(1, collection.Count);

            Binding.BindingDef binding = this.collection[0];
            //Assert the options have been stored on the binding correctly
            Assert.AreEqual(binding.BindingOptions, options);
            Assert.IsTrue(!binding.IsSourceEnumerable);

            //Assert that control service has been passed to the binding
            Assert.IsNotNull(binding.ControlService);
            Assert.AreEqual(this.controlService, binding.ControlService);

            //Assert that the binding has created target and source expression objects
            Assert.IsNotNull(binding.SourceExpression);
            Assert.IsNotNull(binding.TargetExpression);

            Assert.IsFalse(binding.HasValueConverter);
        }
예제 #3
0
        /// <summary>
        /// Bind to a command when the TargetProperty is known
        /// </summary>
        /// <param name="control"></param>
        /// <param name="bindingOptions"></param>
        /// <param name="targetPropertyName"></param>
        public void ExecuteCommandBind(IBindingTarget control, Options bindingOptions, string targetPropertyName)
        {
            BindingDef binding = new BindingDef(control, targetPropertyName, bindingOptions, controlService);

            CommandStorage.Add(binding);
            ExecuteCommandBind(control, binding);
        }
예제 #4
0
        private object AttemptConvert(BindingDef binding, object value, IBindingTarget container)
        {
            if (binding.HasValueConverter)
            {
                IValueConverter converter = binding.GetValueConverterInstance();
                value = converter.Convert(value, binding.ResolveAsTarget(container).Descriptor.PropertyType, binding, CultureInfo.CurrentCulture);
            }

            return(value);
        }
예제 #5
0
        private void ApplyBinding(BindingDef binding, IBindingContainer bindingContainer)
        {
            TargetProperty property = binding.ResolveAsTarget(this.bindingContainer);

            if (property != null)
            {
                object value = property.Value;
                SetProperty(binding, value);
            }
        }
예제 #6
0
        private bool TrySetParent(BindingDef lastBinding)
        {
            if (lastBinding != null)
            {
                //test if the current binding is a child of the previous datacontainer
                IBindingTarget child = controlService.FindControlUnique(lastBinding.Container, this.Container.UniqueID);
                if (child != null)
                {
                    this.Parent = lastBinding;
                }
                else if (lastBinding.Parent != null)
                {
                    TrySetParent(lastBinding.Parent);
                }
            }

            return(this.Parent != null);
        }
예제 #7
0
        public void VerifyRepeaterProgrammaticBindCreatesCorrectBindingObject()
        {
            /*Arrange*/
            List <Child> children = new List <Child> {
                new Child {
                    Name = "Ben"
                }, new Child {
                    Name = "Sam"
                }, new Child {
                    Name = "Dave"
                }, new Child {
                    Name = "Ali"
                }
            };

            this.viewModel.Expect(vm => vm.ChildrensNames).Return(children).Repeat.Once();

            Repeater rpt     = new Repeater();
            Options  options = new Options {
                Path = "ChildrensNames"
            };

            /*Act*/
            object resolvedValue = this.binder.ExecuteBind(new WebformControl(rpt), options, "DataSource");

            /*Assert*/
            Assert.AreEqual(children, resolvedValue);

            Binding.BindingDef binding = this.collection[0];
            Assert.IsTrue(binding.IsSourceEnumerable);

            //collection bindings should always be oneway.
            Assert.AreEqual(BindingMode.OneWay, binding.BindingOptions.Mode);

            //Assert that control service has been passed to the binding
            Assert.IsNotNull(binding.ControlService);
            Assert.AreEqual(this.controlService, binding.ControlService);

            //Assert that the binding has created target and source expression objects
            Assert.IsNotNull(binding.SourceExpression);
            Assert.IsNotNull(binding.TargetExpression);

            Assert.IsFalse(binding.HasValueConverter);
        }
예제 #8
0
        //TODO: Should probably be a member of binding.
        private void SetProperty(BindingDef binding, object value)
        {
            SourceProperty property = binding.SourceExpression.ResolveAsSource(this.DataContext);

            if (property != null && property.Descriptor != null && !property.Descriptor.IsReadOnly)
            {
                object convertedValue  = null;
                Type   destinationType = property.Descriptor.PropertyType;

                if (binding.HasValueConverter)
                {
                    IValueConverter valueConverter = binding.GetValueConverterInstance();

                    convertedValue = valueConverter.ConvertBack(value, property.Descriptor.PropertyType, null, null);
                }
                else
                {
                    if (TypeHelper.IsSimpleType(value.GetType()) && TypeHelper.IsSimpleType(destinationType))
                    {
                        convertedValue = Convert.ChangeType(value, destinationType);
                    }

                    else
                    {
                        TypeConverter converter = TypeDescriptor.GetConverter(destinationType);
                        if (converter != null)
                        {
                            convertedValue = converter.ConvertFrom(value);
                        }
                        else
                        {
                            converter = TypeDescriptor.GetConverter(value.GetType());

                            if (converter != null)
                            {
                                convertedValue = converter.ConvertTo(value, destinationType);
                            }
                        }
                    }
                }

                property.Descriptor.SetValue(property.OwningInstance, convertedValue);
            }
        }
예제 #9
0
        public void NestedAbsolutePathTest()
        {
            /*Arrange*/

            //create a parent binding.
            Binding.BindingDef parent = new Binding.BindingDef(
                new WebformControl(new TextBox())
                , "Text", 0
                , new BindingCollection()
                , new Options {
                Path = "Companies"
            }
                , true, controlService);


            string rawPath = "CompanyName";

            BindingPath path = new BindingPath(rawPath, parent.SourceExpression, PathMode.Absolute);

            var employee1 = new { Name = "Sam" };
            var employee2 = new { Name = "Ben" };
            var employee3 = new { Name = "Ali" };

            var list    = new[] { employee1, employee2, employee3 };
            var company = new { AvailableEmployees = list };

            var companyList = new[] { company };

            var viewModel = new { CompanyName = "Tesco Ltd.", Companies = companyList };

            /*Act*/
            SourceProperty sourceProperty = path.ResolveAsSource(viewModel);

            /*Assert*/
            Assert.IsNotNull(sourceProperty);
            Assert.IsNotNull(sourceProperty.Descriptor);
            Assert.IsNotNull(sourceProperty.OwningInstance);
            Assert.IsNotNull(sourceProperty.Value);
            Assert.AreEqual("CompanyName", sourceProperty.Descriptor.Name);

            Assert.AreEqual(viewModel, sourceProperty.OwningInstance);
            Assert.AreEqual(viewModel.CompanyName, sourceProperty.Value);
        }
예제 #10
0
        public void NestedRelativePathTest()
        {
            /*Arrange*/
            Binding.BindingDef parent = new Binding.BindingDef(
                new WebformControl(new TextBox()),
                "Text",
                new Options()
            {
                Path = "Company"
            },
                controlService);

            string rawPath = "AvailableEmployees.Name";

            BindingPath path = new BindingPath(rawPath, 2, parent.SourceExpression, PathMode.Relative);

            var employee1 = new { Name = "Sam" };
            var employee2 = new { Name = "Ben" };
            var employee3 = new { Name = "Ali" };

            var list    = new[] { employee1, employee2, employee3 };
            var company = new { AvailableEmployees = list };

            var viewModel = new { Company = company };

            /*Act*/
            SourceProperty sourceProperty = path.ResolveAsSource(viewModel);

            /*Assert*/
            Assert.IsNotNull(sourceProperty);
            Assert.IsNotNull(sourceProperty.Descriptor);
            Assert.IsNotNull(sourceProperty.OwningInstance);
            Assert.IsNotNull(sourceProperty.Value);
            Assert.AreEqual("Ali", sourceProperty.Value);
            Assert.AreEqual("Name", sourceProperty.Descriptor.Name);

            //empoyee at the index of 1
            Assert.AreEqual(employee3, sourceProperty.OwningInstance);
            Assert.AreEqual(employee3.Name, sourceProperty.Value);
            Assert.AreEqual("Name", sourceProperty.Descriptor.Name);
        }
예제 #11
0
        private void ExecuteCommandBind(IBindingTarget control, BindingDef binding)
        {
            //Get the ICommandObject from the source
            SourceProperty commandInstance = binding.SourceExpression.ResolveAsSource(this.DataContext);
            object         commandObject   = commandInstance.Value;
            ICommand       iCommand        = commandObject as ICommand;

            //Get the property setter for the event to which we will bind
            TargetEvent evt = binding.ResolveAsTargetEvent(this.bindingContainer);

            //bind
            Type     eventDelegateType = evt.Descriptor.EventHandlerType;
            Delegate handler           = new EventHandler((s, e) => iCommand.Execute(this));

            evt.Descriptor.GetAddMethod().Invoke(evt.OwningControl, new object[] { handler });

            control.Visible = iCommand.CanExecute(this);

            //listen to canExecuteChanged
            iCommand.CanExecuteChanged += new EventHandler((s, e) => control.Visible = iCommand.CanExecute(this));
        }
예제 #12
0
        /// <summary>
        /// Execute a bind in the context of a collection container.
        /// </summary>
        /// <remarks>
        /// Specficy the target control directly.
        /// </remarks>
        /// <param name="control">The target control</param>
        /// <param name="collectionItemContainer">
        /// The collection item container. E.g. In the case of a repeater a RepeaterItem.
        /// This is available from the ItemTemplate control via (IDataItemContainer)container.NamingContainer.
        /// </param>
        ///<param name="targetPropertyName">The property on the targetcontrol.</param>
        /// <param name="bindingOptions"></param>
        /// <returns>The result (value) of the bind</returns>
        public object ExecuteBind(IBindingTarget control, IBindingTarget <IDataItemContainer> collectionItemContainer, Options bindingOptions, string targetPropertyName)
        {
            if (control == null || bindingContainer == null || bindingOptions == null || string.IsNullOrEmpty(bindingOptions.Path))
            {
                return(null);
            }

            object     dataValue = null;
            BindingDef binding   = null;

            IBindingTarget genericContainer = null;
            object         baseContext      = this.DataContext;

            if (bindingOptions.PathMode == PathMode.Relative && collectionItemContainer != null)
            {
                IDataItemContainer containerControl = collectionItemContainer.TargetInstance;
                dataValue = DataBinder.Eval(containerControl.DataItem, bindingOptions.Path);
                bool isCollectionBinding = DetermineIfCollection(control, dataValue);
                binding          = new BindingDef(control, targetPropertyName, containerControl.DataItemIndex, DataStorage, bindingOptions, isCollectionBinding, controlService);
                genericContainer = collectionItemContainer;
            }
            else
            {
                dataValue = DataBinder.Eval(baseContext, bindingOptions.Path);
                bool isCollectionBinding = DetermineIfCollection(control, dataValue);
                binding          = new BindingDef(control, targetPropertyName, bindingOptions, isCollectionBinding, controlService);
                genericContainer = controlService.GetParent(control);
            }

            //determine binding direction is not explicitly set based on the value and contorl
            if (bindingOptions.Mode == BindingMode.Unset)
            {
                bindingOptions.Mode = DetermineBindingDirection(control, dataValue);
            }

            //store the binding
            DataStorage.Add(binding);

            return(AttemptConvert(binding, dataValue, genericContainer));
        }
예제 #13
0
        private List <Control> SetupCollectionUnbindTest(Options options)
        {
            List <Control> createdControls = new List <Control>();

            //Create a repeater from which we will read data
            Repeater rpt = new Repeater();

            rpt.ItemTemplate = new DynamicItemTemplate(new List <Func <Control> > {
                () => new TextBox()
                {
                    ID = "tb"
                }
            });
            var item1 = new Child {
                Name = "Sam"
            };
            var item2 = new Child {
                Name = "Ben"
            };
            var item3 = new Child {
                Name = "Ali"
            };
            var list = new List <Child> {
                item1, item2, item3
            };

            viewModel.ChildrensNames = list;

            //Create a binding collection
            collection = new Binding.BindingCollection();

            //add in the parent binding, this will not be used in the bind but is required for unbind to work within a collection
            collection.Add(new Binding.BindingDef(new WebformControl(rpt), "DataSource", new Options {
                Path = "ChildrensNames"
            }, true, controlService));

            //When the item is created, create a binding for it and add to the binding collection.
            //We will also had the itemtemplate create control to a collection so that we can stick some values
            //in to simulate user input before unbinding to the model.
            int index = 0;

            rpt.ItemDataBound += (s, e) =>
            {
                TextBox        tb        = e.Item.FindControl("tb") as TextBox;
                WebformControl wrappedTb = new WebformControl(tb);
                options.Path = "Name";
                Binding.BindingDef binding = new Binding.BindingDef(wrappedTb, "Text", index, collection, options, false, controlService);
                index++;
                collection.Add(binding);
                createdControls.Add(tb);
            };

            rpt.DataSource = list;


            WebformControl dummyControl = new WebformControl(new TextBox());

            //tell the mock conntrol service to return the collection result when required.
            this.controlService.Expect(cs => cs.FindControlUnique(null, null)).IgnoreArguments()
            .Do(
                new Func <IBindingTarget, string, IBindingTarget>((b, s) =>
            {
                //we only need it return a non-null
                return(dummyControl);
            }));


            int counter = 0;

            //and setup service to return it
            controlService.Expect(cs => cs.Unwrap(null)).IgnoreArguments().Do(new Func <IBindingTarget, object>((t) =>
            {
                Control ctrl = createdControls[counter];
                counter++;
                return(ctrl);
            }));


            //setup viewmodel with default values
            viewModel.ChildrensNames = new List <Child> {
                new Child(), new Child(), new Child()
            };

            //setup the data storage service to return the collection
            dataStorageService.Expect(ds => ds.RetrieveOrCreate <Binding.BindingCollection>(DATA_BINDING_KEY)).Return(collection);
            dataStorageService.Expect(ds => ds.RetrieveOrCreate <Binding.BindingCollection>(COMMAND_BINDING_KEY)).Return(new Binding.BindingCollection());

            //and the viewmodel (we are using the view state binder which will try to resolve the service from storage
            dataStorageService.Expect(ds => ds.Retrieve <object>(null)).IgnoreArguments().Return(viewModel);

            rpt.DataBind();

            return(createdControls);
        }
예제 #14
0
        public void VerifyTextboxInRepeaterProgrammaticBindReturnsCorrectValue()
        {
            /*Arrange*/
            List <Child> children = new List <Child> {
                new Child {
                    Name = "Ben"
                }, new Child {
                    Name = "Sam"
                }, new Child {
                    Name = "Dave"
                }, new Child {
                    Name = "Ali"
                }
            };

            this.viewModel.Expect(vm => vm.ChildrensNames).Return(children).Repeat.Once();

            //tell the mock conntrol service to return the collection result when required.
            this.controlService.Expect(cs => cs.FindControlUnique(null, null)).IgnoreArguments()
            .Do(
                new Func <IBindingTarget, string, IBindingTarget>((b, s) =>
            {
                if (s.EndsWith("tb1"))
                {
                    //we only need it return a non-null
                    return(new WebformControl(new  TextBox()));
                }
                return(null);
            }));


            //create a repeater and set its item template
            Repeater rpt = new Repeater();

            rpt.ItemTemplate = new DynamicItemTemplate(new List <Func <Control> >
            {
                () => new TextBox()
                {
                    ID = "tb1"
                }
            });


            /*Act*/
            Options options = new Options {
                Path = "ChildrensNames"
            };
            object resolvedValue = this.binder.ExecuteBind(new WebformControl(rpt), options, "DataSource");

            rpt.DataSource = resolvedValue;

            //When the repeater item is created bind up child controls and test the values returned from the binder
            rpt.ItemDataBound += (s, e) =>
            {
                RepeaterItem rptItem            = e.Item;
                TextBox      rptItemControl     = rptItem.FindControl("tb1") as TextBox;
                Options      textBoxBindOptions = new Options {
                    Path = "Name"
                };
                object tbResolvedValue = this.binder.ExecuteBind(new WebformControl(rptItemControl), new WebformControl <IDataItemContainer>(rptItem), textBoxBindOptions, "Text");
                Assert.AreEqual(children[rptItem.ItemIndex].Name, tbResolvedValue);
            };

            rpt.DataBind();

            /*Assert*/
            //verify we have an repeater item for each item passed in on the datasource
            Assert.AreEqual(children.Count, rpt.Items.Count);

            //we should have one binding for each child control (4) plus the binding the on the parent(rpt)
            Assert.AreEqual((children.Count + 1), this.collection.Count);

            Binding.BindingDef parentBinding = collection[0];
            Assert.IsTrue(parentBinding.IsSourceEnumerable);
            Assert.IsNotNull(parentBinding.Container);
            Assert.AreEqual(rpt, ((WebformControl)parentBinding.Container).Control);

            //test the child bindings
            for (int i = 1; i < collection.Count; i++)
            {
                Binding.BindingDef childBinding = collection[i];
                Assert.IsTrue(childBinding.Parent == parentBinding);
                Assert.AreEqual(i - 1, childBinding.DataItemIndex);
                Assert.IsFalse(childBinding.IsSourceEnumerable);
            }
        }
예제 #15
0
        private void ExecuteCommandBind(BindingDef binding)
        {
            TargetProperty target = binding.ResolveAsTarget(this.BindingContainer);

            ExecuteCommandBind(target.OwningControl, binding);
        }