Пример #1
0
        /// <summary>
        /// Binds a property to a subject according to a <see cref="BindingMode"/>.
        /// </summary>
        /// <param name="o">The object.</param>
        /// <param name="property">The property to bind.</param>
        /// <param name="source">The binding source.</param>
        /// <param name="mode">The binding mode.</param>
        /// <param name="priority">The binding priority.</param>
        /// <returns>An <see cref="IDisposable"/> which can be used to cancel the binding.</returns>
        public static IDisposable Bind(
            this IPerspexObject o,
            PerspexProperty property,
            ISubject <object> source,
            BindingMode mode,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            Contract.Requires <ArgumentNullException>(o != null);
            Contract.Requires <ArgumentNullException>(property != null);
            Contract.Requires <ArgumentNullException>(source != null);

            switch (mode)
            {
            case BindingMode.Default:
            case BindingMode.OneWay:
                return(o.Bind(property, source, priority));

            case BindingMode.TwoWay:
                return(new CompositeDisposable(
                           o.Bind(property, source, priority),
                           o.GetObservable(property).Subscribe(source)));

            case BindingMode.OneTime:
                return(source.Take(1).Subscribe(x => o.SetValue(property, x, priority)));

            case BindingMode.OneWayToSource:
                return(o.GetObservable(property).Subscribe(source));

            default:
                throw new ArgumentException("Invalid binding mode.");
            }
        }
Пример #2
0
        /// <summary>
        /// Applies an <see cref="InstancedBinding"/> a property on an <see cref="IPerspexObject"/>.
        /// </summary>
        /// <param name="target">The target object.</param>
        /// <param name="property">The property to bind.</param>
        /// <param name="binding">The instanced binding.</param>
        /// <param name="anchor">
        /// An optional anchor from which to locate required context. When binding to objects that
        /// are not in the logical tree, certain types of binding need an anchor into the tree in
        /// order to locate named controls or resources. The <paramref name="anchor"/> parameter
        /// can be used to provice this context.
        /// </param>
        /// <returns>An <see cref="IDisposable"/> which can be used to cancel the binding.</returns>
        public static IDisposable Apply(
            IPerspexObject target,
            PerspexProperty property,
            InstancedBinding binding,
            object anchor)
        {
            Contract.Requires <ArgumentNullException>(target != null);
            Contract.Requires <ArgumentNullException>(property != null);
            Contract.Requires <ArgumentNullException>(binding != null);

            var mode = binding.Mode;

            if (mode == BindingMode.Default)
            {
                mode = property.GetMetadata(target.GetType()).DefaultBindingMode;
            }

            switch (mode)
            {
            case BindingMode.Default:
            case BindingMode.OneWay:
                return(target.Bind(property, binding.Observable ?? binding.Subject, binding.Priority));

            case BindingMode.TwoWay:
                return(new CompositeDisposable(
                           target.Bind(property, binding.Subject, binding.Priority),
                           target.GetObservable(property).Subscribe(binding.Subject)));

            case BindingMode.OneTime:
                var source = binding.Subject ?? binding.Observable;

                if (source != null)
                {
                    return(source.Take(1).Subscribe(x => target.SetValue(property, x, binding.Priority)));
                }
                else
                {
                    target.SetValue(property, binding.Value, binding.Priority);
                    return(Disposable.Empty);
                }

            case BindingMode.OneWayToSource:
                return(target.GetObservable(property).Subscribe(binding.Subject));

            default:
                throw new ArgumentException("Invalid binding mode.");
            }
        }
Пример #3
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(IPerspexObject target, PerspexProperty property, ISubject <object> subject)
        {
            var mode = Mode == BindingMode.Default ?
                       property.GetMetadata(target.GetType()).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;
            }
        }
Пример #4
0
        /// <summary>
        /// Animates a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="T">The property type.</typeparam>
        /// <param name="target">The target object.</param>
        /// <param name="property">The target property.</param>
        /// <param name="start">The value of the property at the start of the animation.</param>
        /// <param name="finish">The value of the property at the end of the animation.</param>
        /// <param name="easing">The easing function to use.</param>
        /// <param name="duration">The duration of the animation.</param>
        /// <returns>An <see cref="Animation"/> that can be used to track or stop the animation.</returns>
        public static Animation <T> Property <T>(
            IPerspexObject target,
            PerspexProperty <T> property,
            T start,
            T finish,
            IEasing <T> easing,
            TimeSpan duration)
        {
            var o = GetTimer(duration).Select(progress => easing.Ease(progress, start, finish));

            return(new Animation <T>(o, target.Bind(property, o, BindingPriority.Animation)));
        }
Пример #5
0
        /// <summary>
        /// Gets a subject for a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="T">The property type.</typeparam>
        /// <param name="o">The object.</param>
        /// <param name="property">The property.</param>
        /// <param name="priority">
        /// The priority with which binding values are written to the object.
        /// </param>
        /// <returns>
        /// An <see cref="ISubject{T}"/> which can be used for two-way binding to/from the
        /// property.
        /// </returns>
        public static ISubject <T> GetSubject <T>(
            this IPerspexObject o,
            PerspexProperty <T> property,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            // TODO: Subject.Create<T> is not yet in stable Rx : once it is, remove the
            // AnonymousSubject classes from this file and use Subject.Create<T>.
            var output = new Subject <T>();
            var result = new AnonymousSubject <T>(
                Observer.Create <T>(
                    x => output.OnNext(x),
                    e => output.OnError(e),
                    () => output.OnCompleted()),
                o.GetObservable(property));

            o.Bind(property, output, priority);
            return(result);
        }
Пример #6
0
        /// <summary>
        /// Binds a property on an <see cref="IPerspexObject"/> to an <see cref="IBinding"/>.
        /// </summary>
        /// <param name="o">The object.</param>
        /// <param name="property">The property to bind.</param>
        /// <param name="binding">The binding.</param>
        /// <returns>An <see cref="IDisposable"/> which can be used to cancel the binding.</returns>
        public static IDisposable Bind(
            this IPerspexObject o,
            PerspexProperty property,
            IBinding binding)
        {
            Contract.Requires <ArgumentNullException>(o != null);
            Contract.Requires <ArgumentNullException>(property != null);
            Contract.Requires <ArgumentNullException>(binding != null);

            var mode = binding.Mode;

            if (mode == BindingMode.Default)
            {
                mode = property.GetMetadata(o.GetType()).DefaultBindingMode;
            }

            return(o.Bind(
                       property,
                       binding.CreateSubject(o, property),
                       mode,
                       binding.Priority));
        }
Пример #7
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(IPerspexObject 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;
            }
        }