Beispiel #1
0
        public ExpressionObserver CreateExpressionObserver(
            IObservablePropertyBag instance, 
            PerspexProperty property)
        {
            IObservable<object> dataContext = null;

            if (property != Control.DataContextProperty)
            {
                dataContext = instance.GetObservable(Control.DataContextProperty);
            }
            else
            {
                var parent = instance.InheritanceParent as IObservablePropertyBag;

                if (parent != null)
                {
                    dataContext = parent.GetObservable(Control.DataContextProperty);
                }
            }

            if (dataContext != null)
            {
                var result = new ExpressionObserver(null, SourcePropertyPath);
                dataContext.Subscribe(x => result.Root = x);
                return result;
            }

            return null;
        }
Beispiel #2
0
        internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject<object> subject)
        {
            var mode = BindingMode == BindingMode.Default ?
                property.DefaultBindingMode : BindingMode;

            switch (mode)
            {
                case BindingMode.Default:
                case BindingMode.OneWay:
                    target.Bind(property, subject);
                    break;
                case BindingMode.TwoWay:
                    target.BindTwoWay(property, subject);
                    break;
                case BindingMode.OneTime:
                    target.GetObservable(Control.DataContextProperty).Subscribe(dataContext =>
                    {
                        subject.Take(1).Subscribe(x => target.SetValue(property, x));
                    });                    
                    break;
                case BindingMode.OneWayToSource:
                    target.GetObservable(property).Subscribe(subject);
                    break;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Creates a subject that can be used to get and set the value of the binding.
        /// </summary>
        /// <param name="target">The target instance.</param>
        /// <param name="targetType">The type of the target property.</param>
        /// <param name="targetIsDataContext">
        /// Whether the target property is the DataContext property.
        /// </param>
        /// <returns>An <see cref="ISubject{object}"/>.</returns>
        public ISubject<object> CreateSubject(
            IObservablePropertyBag target,
            Type targetType,
            bool targetIsDataContext = false)
        {
            ExpressionObserver observer;

            if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
            {
                observer = CreateDataContextExpressionSubject(target, targetIsDataContext);
            }
            else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
            {
                observer = CreateTemplatedParentExpressionSubject(target);
            }
            else
            {
                throw new NotSupportedException();
            }

            return new ExpressionSubject(
                observer, 
                targetType, 
                Converter ?? DefaultValueConverter.Instance);
        }
Beispiel #4
0
        public void Bind(IObservablePropertyBag instance, PerspexProperty property)
        {
            var subject = CreateSubject(instance, property);

            if (subject != null)
            {
                Bind(instance, property, subject);
            }
        }
Beispiel #5
0
        public void Bind(IObservablePropertyBag instance, PerspexProperty property)
        {
            var subject = new ExpressionSubject(CreateExpressionObserver(instance, property));

            if (subject != null)
            {
                Bind(instance, property, subject);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Applies the binding to a property on an instance.
        /// </summary>
        /// <param name="instance">The target instance.</param>
        /// <param name="property">The target property.</param>
        public void Bind(IObservablePropertyBag instance, PerspexProperty property)
        {
            var subject = CreateSubject(
                instance, 
                property.PropertyType,
                property == Control.DataContextProperty);

            if (subject != null)
            {
                Bind(instance, property, subject);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Applies the binding to a property on an instance.
        /// </summary>
        /// <param name="instance">The target instance.</param>
        /// <param name="property">The target property.</param>
        public void Bind(IObservablePropertyBag instance, PerspexProperty property)
        {
            Contract.Requires<ArgumentNullException>(instance != null);
            Contract.Requires<ArgumentNullException>(property != null);

            var subject = CreateSubject(
                instance,
                property.PropertyType,
                property == Control.DataContextProperty);

            if (subject != null)
            {
                Bind(instance, property, subject);
            }
        }
Beispiel #8
0
        public ISubject<object> CreateSubject(
            IObservablePropertyBag instance, 
            PerspexProperty property)
        {
            if (Converter == null)
            {
                throw new NotSupportedException("MultiBinding without Converter not currently supported.");
            }

            var result = new Subject<object>();
            var children = Bindings.Select(x => x.CreateExpressionSubject(instance, property));
            var input = Observable.CombineLatest(children).Select(x =>
                Converter.Convert(x, property.PropertyType, null, CultureInfo.CurrentUICulture));
            input.Subscribe(result);
            return result;
        }
Beispiel #9
0
        public ISubject <object> CreateSubject(
            IObservablePropertyBag instance,
            PerspexProperty property)
        {
            if (Converter == null)
            {
                throw new NotSupportedException("MultiBinding without Converter not currently supported.");
            }

            var result   = new Subject <object>();
            var children = Bindings.Select(x => x.CreateExpressionSubject(instance, property));
            var input    = Observable.CombineLatest(children).Select(x =>
                                                                     Converter.Convert(x, property.PropertyType, null, CultureInfo.CurrentUICulture));

            input.Subscribe(result);
            return(result);
        }
Beispiel #10
0
        private ExpressionObserver CreateTemplatedParentSubject(
            IObservablePropertyBag target,
            string path)
        {
            Contract.Requires <ArgumentNullException>(target != null);

            var update = target.GetObservable(Control.TemplatedParentProperty)
                         .Skip(1)
                         .Select(_ => Unit.Default);

            var result = new ExpressionObserver(
                () => target.GetValue(Control.TemplatedParentProperty),
                path,
                update);

            return(result);
        }
Beispiel #11
0
        /// <summary>
        /// Creates a subject that can be used to get and set the value of the binding.
        /// </summary>
        /// <param name="target">The target instance.</param>
        /// <param name="targetType">The type of the target property.</param>
        /// <param name="targetIsDataContext">
        /// Whether the target property is the DataContext property.
        /// </param>
        /// <returns>An <see cref="ISubject{object}"/>.</returns>
        public ISubject<object> CreateSubject(
            IObservablePropertyBag target, 
            Type targetType,
            bool targetIsDataContext = false)
        {
            if (Converter == null)
            {
                throw new NotSupportedException("MultiBinding without Converter not currently supported.");
            }

            var result = new BehaviorSubject<object>(PerspexProperty.UnsetValue);
            var children = Bindings.Select(x => x.CreateSubject(target, typeof(object)));
            var input = Observable.CombineLatest(children).Select(x =>
                Converter.Convert(x, targetType, null, CultureInfo.CurrentUICulture));
            input.Subscribe(result);
            return result;
        }
Beispiel #12
0
        /// <summary>
        /// Creates a subject that can be used to get and set the value of the binding.
        /// </summary>
        /// <param name="target">The target instance.</param>
        /// <param name="targetType">The type of the target property.</param>
        /// <param name="targetIsDataContext">
        /// Whether the target property is the DataContext property.
        /// </param>
        /// <returns>An <see cref="ISubject{object}"/>.</returns>
        public ISubject <object> CreateSubject(
            IObservablePropertyBag target,
            Type targetType,
            bool targetIsDataContext = false)
        {
            Contract.Requires <ArgumentNullException>(target != null);
            Contract.Requires <ArgumentNullException>(targetType != null);

            var pathInfo = ParsePath(Path);

            ValidateState(pathInfo);

            ExpressionObserver observer;

            if (pathInfo.ElementName != null || ElementName != null)
            {
                observer = CreateElementSubject(
                    (IControl)target,
                    pathInfo.ElementName ?? ElementName,
                    pathInfo.Path);
            }
            else if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
            {
                observer = CreateDataContextSubject(
                    target,
                    pathInfo.Path,
                    targetIsDataContext);
            }
            else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
            {
                observer = CreateTemplatedParentSubject(
                    target,
                    pathInfo.Path);
            }
            else
            {
                throw new NotSupportedException();
            }

            return(new ExpressionSubject(
                       observer,
                       targetType,
                       Converter ?? DefaultValueConverter.Instance,
                       ConverterParameter));
        }
Beispiel #13
0
        private ExpressionObserver CreateTemplatedParentExpressionSubject(IObservablePropertyBag target)
        {
            var result = new ExpressionObserver(
                () => target.GetValue(Control.TemplatedParentProperty),
                GetExpression());

            if (target.GetValue(Control.TemplatedParentProperty) == null)
            {
                // TemplatedParent should only be set once, so only listen for the first non-null
                // value.
                target.GetObservable(Control.TemplatedParentProperty)
                .Where(x => x != null)
                .Take(1)
                .Subscribe(x => result.UpdateRoot());
            }

            return(result);
        }
Beispiel #14
0
        /// <summary>
        /// Creates a subject that can be used to get and set the value of the binding.
        /// </summary>
        /// <param name="target">The target instance.</param>
        /// <param name="targetType">The type of the target property.</param>
        /// <param name="targetIsDataContext">
        /// Whether the target property is the DataContext property.
        /// </param>
        /// <returns>An <see cref="ISubject{object}"/>.</returns>
        public ISubject <object> CreateSubject(
            IObservablePropertyBag target,
            Type targetType,
            bool targetIsDataContext = false)
        {
            if (Converter == null)
            {
                throw new NotSupportedException("MultiBinding without Converter not currently supported.");
            }

            var result   = new BehaviorSubject <object>(PerspexProperty.UnsetValue);
            var children = Bindings.Select(x => x.CreateSubject(target, typeof(object)));
            var input    = Observable.CombineLatest(children).Select(x =>
                                                                     Converter.Convert(x, targetType, null, CultureInfo.CurrentUICulture));

            input.Subscribe(result);
            return(result);
        }
Beispiel #15
0
        /// <summary>
        /// Creates a subject that can be used to get and set the value of the binding.
        /// </summary>
        /// <param name="target">The target instance.</param>
        /// <param name="targetType">The type of the target property.</param>
        /// <param name="targetIsDataContext">
        /// Whether the target property is the DataContext property.
        /// </param>
        /// <returns>An <see cref="ISubject{object}"/>.</returns>
        public ISubject<object> CreateSubject(
            IObservablePropertyBag target,
            Type targetType,
            bool targetIsDataContext = false)
        {
            Contract.Requires<ArgumentNullException>(target != null);
            Contract.Requires<ArgumentNullException>(targetType != null);

            var pathInfo = ParsePath(Path);
            ValidateState(pathInfo);

            ExpressionObserver observer;

            if (pathInfo.ElementName != null || ElementName != null)
            {
                observer = CreateElementSubject(
                    (IControl)target, 
                    pathInfo.ElementName ?? ElementName, 
                    pathInfo.Path);
            }
            else if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
            {
                observer = CreateDataContextSubject(
                    target, 
                    pathInfo.Path,
                    targetIsDataContext);
            }
            else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
            {
                observer = CreateTemplatedParentSubject(
                    target,
                    pathInfo.Path);
            }
            else
            {
                throw new NotSupportedException();
            }

            return new ExpressionSubject(
                observer,
                targetType,
                Converter ?? DefaultValueConverter.Instance,
                ConverterParameter);
        }
Beispiel #16
0
        public ExpressionObserver CreateExpressionObserver(
            IObservablePropertyBag instance,
            PerspexProperty property)
        {
            var dataContextHost = property != Control.DataContextProperty ?
                                  instance :
                                  instance.InheritanceParent as IObservablePropertyBag;

            if (dataContextHost != null)
            {
                var result = new ExpressionObserver(
                    () => dataContextHost.GetValue(Control.DataContextProperty),
                    SourcePropertyPath);
                dataContextHost.GetObservable(Control.DataContextProperty).Subscribe(x =>
                                                                                     result.UpdateRoot());
                return(result);
            }

            return(null);
        }
Beispiel #17
0
        private ExpressionObserver CreateDataContextExpressionSubject(
            IObservablePropertyBag target,
            bool targetIsDataContext)
        {
            var dataContextHost = targetIsDataContext ?
                                  target.InheritanceParent as IObservablePropertyBag : target;

            if (dataContextHost != null)
            {
                var result = new ExpressionObserver(
                    () => dataContextHost.GetValue(Control.DataContextProperty),
                    GetExpression());
                dataContextHost.GetObservable(Control.DataContextProperty).Subscribe(x =>
                                                                                     result.UpdateRoot());
                return(result);
            }
            else
            {
                throw new InvalidOperationException(
                          "Cannot bind to DataContext of object with no parent.");
            }
        }
Beispiel #18
0
        private ExpressionObserver CreateTemplatedParentSubject(
            IObservablePropertyBag target,
            string path)
        {
            Contract.Requires <ArgumentNullException>(target != null);

            var result = new ExpressionObserver(
                () => target.GetValue(Control.TemplatedParentProperty),
                path);

            if (target.GetValue(Control.TemplatedParentProperty) == null)
            {
                // TemplatedParent should only be set once, so only listen for the first non-null
                // value.
                target.GetObservable(Control.TemplatedParentProperty)
                .Where(x => x != null)
                .Take(1)
                .Subscribe(x => result.UpdateRoot());
            }

            return(result);
        }
Beispiel #19
0
        public ISubject <object> CreateExpressionSubject(
            IObservablePropertyBag instance,
            PerspexProperty property)
        {
            ExpressionObserver observer;

            if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
            {
                observer = CreateDataContextExpressionSubject(instance, property);
            }
            else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
            {
                observer = CreateTemplatedParentExpressionSubject(instance, property);
            }
            else
            {
                throw new NotSupportedException();
            }

            return(new ExpressionSubject(
                       observer,
                       property.PropertyType,
                       Converter ?? DefaultValueConverter.Instance));
        }
Beispiel #20
0
        public ISubject<object> CreateExpressionSubject(
            IObservablePropertyBag instance, 
            PerspexProperty property)
        {
            ExpressionObserver observer;

            if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
            {
                observer = CreateDataContextExpressionSubject(instance, property);
            }
            else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
            {
                observer = CreateTemplatedParentExpressionSubject(instance, property);
            }
            else
            {
                throw new NotSupportedException();
            }

            return new ExpressionSubject(
                observer, 
                property.PropertyType, 
                Converter ?? DefaultValueConverter.Instance);
        }
Beispiel #21
0
        internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject<object> subject)
        {
            var mode = Mode == BindingMode.Default ?
                property.DefaultBindingMode : Mode;

            switch (mode)
            {
                case BindingMode.Default:
                case BindingMode.OneWay:
                    target.Bind(property, subject, Priority);
                    break;
                case BindingMode.TwoWay:
                    throw new NotSupportedException("TwoWay MultiBinding not currently supported.");
                case BindingMode.OneTime:
                    target.GetObservable(Control.DataContextProperty).Subscribe(dataContext =>
                    {
                        subject.Take(1).Subscribe(x => target.SetValue(property, x, Priority));
                    });                    
                    break;
                case BindingMode.OneWayToSource:
                    target.GetObservable(property).Subscribe(subject);
                    break;
            }
        }
Beispiel #22
0
        private ExpressionObserver CreateTemplatedParentExpressionSubject(IObservablePropertyBag target)
        {
            var result = new ExpressionObserver(
                () => target.GetValue(Control.TemplatedParentProperty),
                GetExpression());

            if (target.GetValue(Control.TemplatedParentProperty) == null)
            {
                // TemplatedParent should only be set once, so only listen for the first non-null
                // value.
                target.GetObservable(Control.TemplatedParentProperty)
                    .Where(x => x != null)
                    .Take(1)
                    .Subscribe(x => result.UpdateRoot());
            }

            return result;
        }
Beispiel #23
0
        private ExpressionObserver CreateTemplatedParentSubject(
            IObservablePropertyBag target,
            string path)
        {
            Contract.Requires<ArgumentNullException>(target != null);

            var update = target.GetObservable(Control.TemplatedParentProperty)
                .Skip(1)
                .Select(_ => Unit.Default);

            var result = new ExpressionObserver(
                () => target.GetValue(Control.TemplatedParentProperty),
                path,
                update);

            return result;
        }
Beispiel #24
0
        public ExpressionObserver CreateDataContextExpressionSubject(
            IObservablePropertyBag instance,
            PerspexProperty property)
        {
            var dataContextHost = property != Control.DataContextProperty ?
                instance :
                instance.InheritanceParent as IObservablePropertyBag;

            if (dataContextHost != null)
            {
                var result = new ExpressionObserver(
                    () => dataContextHost.GetValue(Control.DataContextProperty),
                    GetExpression());
                dataContextHost.GetObservable(Control.DataContextProperty).Subscribe(x =>
                    result.UpdateRoot());
                return result;
            }

            return null;
        }
Beispiel #25
0
        /// <summary>
        /// Applies a binding subject to a property on an instance.
        /// </summary>
        /// <param name="target">The target instance.</param>
        /// <param name="property">The target property.</param>
        /// <param name="subject">The binding subject.</param>
        internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject<object> subject)
        {
            Contract.Requires<ArgumentNullException>(target != null);
            Contract.Requires<ArgumentNullException>(property != null);
            Contract.Requires<ArgumentNullException>(subject != null);

            var mode = Mode == BindingMode.Default ?
                property.DefaultBindingMode : Mode;

            switch (mode)
            {
                case BindingMode.Default:
                case BindingMode.OneWay:
                    target.Bind(property, subject, Priority);
                    break;
                case BindingMode.TwoWay:
                    target.BindTwoWay(property, subject, Priority);
                    break;
                case BindingMode.OneTime:
                    target.GetObservable(Control.DataContextProperty).Subscribe(dataContext =>
                    {
                        subject.Take(1).Subscribe(x => target.SetValue(property, x, Priority));
                    });
                    break;
                case BindingMode.OneWayToSource:
                    target.GetObservable(property).Subscribe(subject);
                    break;
            }
        }
Beispiel #26
0
        private ExpressionObserver CreateDataContextSubject(
            IObservablePropertyBag target,
            string path,
            bool targetIsDataContext)
        {
            Contract.Requires<ArgumentNullException>(target != null);

            if (!targetIsDataContext)
            {
                var result = new ExpressionObserver(
                    () => target.GetValue(Control.DataContextProperty),
                    path);

                /// TODO: Instead of doing this, make the ExpressionObserver accept an "update"
                /// observable as doing it this way can will cause a leak in Binding as this 
                /// observable is never unsubscribed.
                target.GetObservable(Control.DataContextProperty).Subscribe(x =>
                    result.UpdateRoot());

                return result;
            }
            else
            {
                return new ExpressionObserver(
                    target.GetObservable(Visual.VisualParentProperty)
                          .OfType<IObservablePropertyBag>()
                          .Select(x => x.GetObservable(Control.DataContextProperty))
                          .Switch(),
                    path);
            }
        }
Beispiel #27
0
        private ExpressionObserver CreateDataContextExpressionSubject(
            IObservablePropertyBag target,
            bool targetIsDataContext)
        {
            var dataContextHost = targetIsDataContext ?
                target.InheritanceParent as IObservablePropertyBag : target;

            if (dataContextHost != null)
            {
                var result = new ExpressionObserver(
                    () => dataContextHost.GetValue(Control.DataContextProperty),
                    GetExpression());
                dataContextHost.GetObservable(Control.DataContextProperty).Subscribe(x =>
                    result.UpdateRoot());
                return result;
            }
            else
            {
                throw new InvalidOperationException(
                    "Cannot bind to DataContext of object with no parent.");
            }
        }
Beispiel #28
0
        private ExpressionObserver CreateTemplatedParentSubject(
            IObservablePropertyBag target,
            string path)
        {
            Contract.Requires<ArgumentNullException>(target != null);

            var result = new ExpressionObserver(
                () => target.GetValue(Control.TemplatedParentProperty),
                path);

            if (target.GetValue(Control.TemplatedParentProperty) == null)
            {
                // TemplatedParent should only be set once, so only listen for the first non-null
                // value.
                target.GetObservable(Control.TemplatedParentProperty)
                    .Where(x => x != null)
                    .Take(1)
                    .Subscribe(x => result.UpdateRoot());
            }

            return result;
        }
Beispiel #29
0
        private ExpressionObserver CreateDataContextSubject(
            IObservablePropertyBag target,
            string path,
            bool targetIsDataContext)
        {
            Contract.Requires<ArgumentNullException>(target != null);

            if (!targetIsDataContext)
            {
                var update = target.GetObservable(Control.DataContextProperty)
                    .Skip(1)
                    .Select(_ => Unit.Default);
                var result = new ExpressionObserver(
                    () => target.GetValue(Control.DataContextProperty),
                    path,
                    update);

                return result;
            }
            else
            {
                return new ExpressionObserver(
                    target.GetObservable(Visual.VisualParentProperty)
                          .OfType<IObservablePropertyBag>()
                          .Select(x => x.GetObservable(Control.DataContextProperty))
                          .Switch(),
                    path);
            }
        }