コード例 #1
0
        /// <summary>
        /// Checks whether a <see cref="PerspexProperty"/> is set on this object.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>True if the property is set, otherwise false.</returns>
        public bool IsSet(PerspexProperty property)
        {
            Contract.Requires <ArgumentNullException>(property != null);

            PriorityValue value;

            if (_values.TryGetValue(property, out value))
            {
                return(value.Value != PerspexProperty.UnsetValue);
            }

            return(false);
        }
コード例 #2
0
        /// <summary>
        /// Gets a <see cref="PerspexProperty"/> value.
        /// </summary>
        /// <typeparam name="T">The type of the property.</typeparam>
        /// <param name="property">The property.</param>
        /// <returns>The value.</returns>
        public T GetValue <T>(PerspexProperty <T> property)
        {
            Contract.Requires <ArgumentNullException>(property != null);

            if (property.IsDirect)
            {
                return(((PerspexProperty <T>)GetRegistered(property)).Getter(this));
            }
            else
            {
                return((T)GetValue((PerspexProperty)property));
            }
        }
コード例 #3
0
        /// <summary>
        /// Binds a <see cref="PerspexProperty"/> to an observable.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="source">The observable.</param>
        /// <param name="priority">The priority of the binding.</param>
        /// <returns>
        /// A disposable which can be used to terminate the binding.
        /// </returns>
        public IDisposable Bind(
            PerspexProperty property,
            IObservable <object> source,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            Contract.Requires <ArgumentNullException>(property != null);
            VerifyAccess();

            if (property.IsDirect)
            {
                property = GetRegistered(property);

                if (property.Setter == null)
                {
                    throw new ArgumentException($"The property {property.Name} is readonly.");
                }

                _propertyLog.Verbose(
                    "Bound {Property} to {Binding} with priority LocalValue",
                    property,
                    GetDescription(source));

                return(source
                       .Select(x => TypeUtilities.CastOrDefault(x, property.PropertyType))
                       .Subscribe(x => SetValue(property, x)));
            }
            else
            {
                PriorityValue v;

                if (!PerspexPropertyRegistry.Instance.IsRegistered(this, property))
                {
                    ThrowNotRegistered(property);
                }

                if (!_values.TryGetValue(property, out v))
                {
                    v = CreatePriorityValue(property);
                    _values.Add(property, v);
                }

                _propertyLog.Verbose(
                    "Bound {Property} to {Binding} with priority {Priority}",
                    property,
                    GetDescription(source),
                    priority);

                return(v.Add(source, (int)priority));
            }
        }
コード例 #4
0
        /// <inheritdoc/>
        public override void Merge(PropertyMetadata baseMetadata, PerspexProperty property)
        {
            base.Merge(baseMetadata, property);

            var src = baseMetadata as DirectPropertyMetadata <TValue>;

            if (src != null)
            {
                if (UnsetValue == null)
                {
                    UnsetValue = src.UnsetValue;
                }
            }
        }
コード例 #5
0
ファイル: PerspexObject.cs プロジェクト: vbfool/Perspex
 /// <summary>
 /// Sets the backing field for a direct perspex property, raising the
 /// <see cref="PropertyChanged"/> event if the value has changed.
 /// </summary>
 /// <typeparam name="T">The type of the property.</typeparam>
 /// <param name="property">The property.</param>
 /// <param name="field">The backing field.</param>
 /// <param name="value">The value.</param>
 /// <returns>
 /// True if the value changed, otherwise false.
 /// </returns>
 protected bool SetAndRaise <T>(PerspexProperty <T> property, ref T field, T value)
 {
     VerifyAccess();
     if (!object.Equals(field, value))
     {
         var old = field;
         field = value;
         RaisePropertyChanged(property, old, value, BindingPriority.LocalValue);
         return(true);
     }
     else
     {
         return(false);
     }
 }
コード例 #6
0
ファイル: PerspexObject.cs プロジェクト: vbfool/Perspex
        /// <summary>
        /// Sets a <see cref="PerspexProperty"/> value.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="value">The value.</param>
        /// <param name="priority">The priority of the value.</param>
        public void SetValue(
            PerspexProperty property,
            object value,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            Contract.Requires <ArgumentNullException>(property != null);
            VerifyAccess();

            if (property.IsDirect)
            {
                var accessor = (IDirectPropertyAccessor)GetRegistered(property);
                LogPropertySet(property, value, priority);
                accessor.SetValue(this, DirectUnsetToDefault(value, property));
            }
            else
            {
                PriorityValue v;
                var           originalValue = value;

                if (!PerspexPropertyRegistry.Instance.IsRegistered(this, property))
                {
                    ThrowNotRegistered(property);
                }

                if (!TypeUtilities.TryCast(property.PropertyType, value, out value))
                {
                    throw new ArgumentException(string.Format(
                                                    "Invalid value for Property '{0}': '{1}' ({2})",
                                                    property.Name,
                                                    originalValue,
                                                    originalValue?.GetType().FullName ?? "(null)"));
                }

                if (!_values.TryGetValue(property, out v))
                {
                    if (value == PerspexProperty.UnsetValue)
                    {
                        return;
                    }

                    v = CreatePriorityValue(property);
                    _values.Add(property, v);
                }

                LogPropertySet(property, value, priority);
                v.SetValue(value, (int)priority);
            }
        }
コード例 #7
0
        /// <summary>
        /// Initiates a two-way binding between a <see cref="PerspexProperty"/> and an
        /// <see cref="ISubject{Object}"/>.
        /// </summary>
        /// <param name="property">The property on this object.</param>
        /// <param name="source">The subject to bind to.</param>
        /// <param name="priority">The priority of the binding.</param>
        /// <returns>
        /// A disposable which can be used to terminate the binding.
        /// </returns>
        /// <remarks>
        /// The binding is first carried out from <paramref name="source"/> to this.
        /// </remarks>
        public IDisposable BindTwoWay(
            PerspexProperty property,
            ISubject <object> source,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            VerifyAccess();
            _propertyLog.Verbose(
                "Bound two way {Property} to {Binding} with priority {Priority}",
                property,
                GetDescription(source),
                priority);

            return(new CompositeDisposable(
                       Bind(property, source),
                       GetObservable(property).Subscribe(source)));
        }
コード例 #8
0
        /// <summary>
        /// Raises the <see cref="PropertyChanged"/> event.
        /// </summary>
        /// <param name="property">The property that has changed.</param>
        /// <param name="oldValue">The old property value.</param>
        /// <param name="newValue">The new property value.</param>
        private void RaisePropertyChanged(PerspexProperty property, object oldValue, object newValue)
        {
            Contract.Requires <NullReferenceException>(property != null);

            if (this.PropertyChanged != null)
            {
                PerspexPropertyChangedEventArgs e = new PerspexPropertyChangedEventArgs(this, property, oldValue, newValue);
                property.NotifyChanged(e);
                this.PropertyChanged(this, e);
            }

            if (this.inpcChanged != null)
            {
                PropertyChangedEventArgs e = new PropertyChangedEventArgs(property.Name);
                this.inpcChanged(this, e);
            }
        }
コード例 #9
0
        /// <summary>
        /// Initiates a two-way binding between <see cref="PerspexProperty"/>s.
        /// </summary>
        /// <param name="property">The property on this object.</param>
        /// <param name="source">The source object.</param>
        /// <param name="sourceProperty">The property on the source object.</param>
        /// <param name="priority">The priority of the binding.</param>
        /// <returns>
        /// A disposable which can be used to terminate the binding.
        /// </returns>
        /// <remarks>
        /// The binding is first carried out from <paramref name="source"/> to this.
        /// </remarks>
        public IDisposable BindTwoWay(
            PerspexProperty property,
            PerspexObject source,
            PerspexProperty sourceProperty,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            VerifyAccess();
            _propertyLog.Verbose(
                "Bound two way {Property} to {Binding} with priority {Priority}",
                property,
                source,
                priority);

            return(new CompositeDisposable(
                       Bind(property, source.GetObservable(sourceProperty)),
                       source.Bind(sourceProperty, GetObservable(property))));
        }
コード例 #10
0
        /// <summary>
        /// Raises the <see cref="PropertyChanged"/> event.
        /// </summary>
        /// <param name="property">The property that has changed.</param>
        /// <param name="oldValue">The old property value.</param>
        /// <param name="newValue">The new property value.</param>
        /// <param name="priority">The priority of the binding that produced the value.</param>
        protected void RaisePropertyChanged(
            PerspexProperty property,
            object oldValue,
            object newValue,
            BindingPriority priority)
        {
            Contract.Requires <ArgumentNullException>(property != null);
            VerifyAccess();

            PerspexPropertyChangedEventArgs e = new PerspexPropertyChangedEventArgs(
                this,
                property,
                oldValue,
                newValue,
                priority);

            if (property.Notifying != null)
            {
                property.Notifying(this, true);
            }

            try
            {
                OnPropertyChanged(e);
                property.NotifyChanged(e);

                if (PropertyChanged != null)
                {
                    PropertyChanged(this, e);
                }

                if (_inpcChanged != null)
                {
                    PropertyChangedEventArgs e2 = new PropertyChangedEventArgs(property.Name);
                    _inpcChanged(this, e2);
                }
            }
            finally
            {
                if (property.Notifying != null)
                {
                    property.Notifying(this, false);
                }
            }
        }
コード例 #11
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);
        }
コード例 #12
0
ファイル: PerspexObject.cs プロジェクト: vbfool/Perspex
        /// <summary>
        /// Creates a <see cref="PriorityValue"/> for a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>The <see cref="PriorityValue"/>.</returns>
        private PriorityValue CreatePriorityValue(PerspexProperty property)
        {
            var validate = ((IStyledPropertyAccessor)property).GetValidationFunc(GetType());
            Func <object, object> validate2 = null;

            if (validate != null)
            {
                validate2 = v => validate(this, v);
            }

            PriorityValue result = new PriorityValue(
                this,
                property,
                property.PropertyType,
                validate2);

            return(result);
        }
コード例 #13
0
        /// <summary>
        /// Registers a <see cref="PerspexProperty"/> on a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="property">The property.</param>
        /// <remarks>
        /// You won't usually want to call this method directly, instead use the
        /// <see cref="PerspexProperty.Register"/> method.
        /// </remarks>
        public static void Register(Type type, PerspexProperty property)
        {
            Contract.Requires <NullReferenceException>(type != null);
            Contract.Requires <NullReferenceException>(property != null);

            List <PerspexProperty> list;

            if (!registered.TryGetValue(type, out list))
            {
                list = new List <PerspexProperty>();
                registered.Add(type, list);
            }

            if (!list.Contains(property))
            {
                list.Add(property);
            }
        }
コード例 #14
0
        /// <summary>
        /// Sets a <see cref="PerspexProperty"/> value.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="value">The value.</param>
        public void SetValue(PerspexProperty property, object value)
        {
            Contract.Requires <NullReferenceException>(property != null);

            const int     Priority = (int)BindingPriority.LocalValue;
            PriorityValue v;

            if (!this.IsRegistered(property))
            {
                throw new InvalidOperationException(string.Format(
                                                        "Property '{0}' not registered on '{1}'",
                                                        property.Name,
                                                        this.GetType()));
            }

            if (!PriorityValue.IsValidValue(value, property.PropertyType))
            {
                throw new InvalidOperationException(string.Format(
                                                        "Invalid value for Property '{0}': {1} ({2})",
                                                        property.Name,
                                                        value,
                                                        value.GetType().FullName));
            }

            if (!this.values.TryGetValue(property, out v))
            {
                if (value == PerspexProperty.UnsetValue)
                {
                    return;
                }

                v = this.CreatePriorityValue(property);
                this.values.Add(property, v);
            }

            this.Log().Debug(
                "Set local value of {0}.{1} (#{2:x8}) to {3}",
                this.GetType().Name,
                property.Name,
                this.GetHashCode(),
                value);

            v.Replace(Observable.Never <object>().StartWith(value), Priority);
        }
コード例 #15
0
        /// <summary>
        /// Sets a <see cref="PerspexProperty"/> value.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="value">The value.</param>
        /// <param name="priority">The priority of the value.</param>
        public void SetValue(
            PerspexProperty property,
            object value,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            Contract.Requires <NullReferenceException>(property != null);

            PriorityValue v;

            if (!IsRegistered(property))
            {
                throw new InvalidOperationException(string.Format(
                                                        "Property '{0}' not registered on '{1}'",
                                                        property.Name,
                                                        GetType()));
            }

            if (!TypeUtilities.TryCast(property.PropertyType, value, out value))
            {
                throw new InvalidOperationException(string.Format(
                                                        "Invalid value for Property '{0}': {1} ({2})",
                                                        property.Name,
                                                        value,
                                                        value?.GetType().FullName ?? "(null)"));
            }

            if (!_values.TryGetValue(property, out v))
            {
                if (value == PerspexProperty.UnsetValue)
                {
                    return;
                }

                v = CreatePriorityValue(property);
                _values.Add(property, v);
            }

            _propertyLog.Verbose(
                "Set {Property} to {$Value} with priority {Priority}",
                property,
                value,
                priority);
            v.SetDirectValue(value, (int)priority);
        }
コード例 #16
0
        /// <inheritdoc/>
        public override void Merge(PropertyMetadata baseMetadata, PerspexProperty property)
        {
            base.Merge(baseMetadata, property);

            var src = baseMetadata as StyledPropertyMetadata <TValue>;

            if (src != null)
            {
                if (DefaultValue == null)
                {
                    DefaultValue = src.DefaultValue;
                }

                if (Validate == null)
                {
                    Validate = src.Validate;
                }
            }
        }
コード例 #17
0
        /// <summary>
        /// Creates a <see cref="PriorityValue"/> for a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>The <see cref="PriorityValue"/>.</returns>
        private PriorityValue CreatePriorityValue(PerspexProperty property)
        {
            var validate = ((IStyledPropertyAccessor)property).GetValidationFunc(GetType());
            Func <object, object> validate2 = null;

            if (validate != null)
            {
                validate2 = v => validate(this, v);
            }

            PriorityValue result = new PriorityValue(
                this,
                property.Name,
                property.PropertyType,
                validate2);

            result.Changed.Subscribe(x =>
            {
                object oldValue = (x.Item1 == PerspexProperty.UnsetValue) ?
                                  GetDefaultValue(property) :
                                  x.Item1;
                object newValue = (x.Item2 == PerspexProperty.UnsetValue) ?
                                  GetDefaultValue(property) :
                                  x.Item2;

                if (!Equals(oldValue, newValue))
                {
                    RaisePropertyChanged(property, oldValue, newValue, (BindingPriority)result.ValuePriority);

                    Logger.Verbose(
                        LogArea.Property,
                        this,
                        "{Property} changed from {$Old} to {$Value} with priority {Priority}",
                        property,
                        oldValue,
                        newValue,
                        (BindingPriority)result.ValuePriority);
                }
            });

            return(result);
        }
コード例 #18
0
        /// <summary>
        /// Registers the direct property on another type.
        /// </summary>
        /// <typeparam name="TOwner">The type of the additional owner.</typeparam>
        /// <returns>The property.</returns>
        public PerspexProperty <TValue> AddOwner <TOwner>(
            Func <TOwner, TValue> getter,
            Action <TOwner, TValue> setter = null)
            where TOwner : PerspexObject
        {
            if (!IsDirect)
            {
                throw new InvalidOperationException(
                          "This overload of AddOwner is for direct PerspexProperties.");
            }

            var result = new PerspexProperty <TValue>(
                this,
                typeof(TOwner),
                CastReturn(getter),
                CastParam1(setter));

            PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result);
            return(result);
        }
コード例 #19
0
        /// <summary>
        /// Registers an attached <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="TOwner">The type of the class that is registering the property.</typeparam>
        /// <typeparam name="THost">The type of the class that the property is to be registered on.</typeparam>
        /// <typeparam name="TValue">The type of the property's value.</typeparam>
        /// <param name="name">The name of the property.</param>
        /// <param name="defaultValue">The default value of the property.</param>
        /// <param name="inherits">Whether the property inherits its value.</param>
        /// <param name="defaultBindingMode">The default binding mode for the property.</param>
        /// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
        public static PerspexProperty <TValue> RegisterAttached <TOwner, THost, TValue>(
            string name,
            TValue defaultValue            = default(TValue),
            bool inherits                  = false,
            BindingMode defaultBindingMode = BindingMode.OneWay)
            where TOwner : PerspexObject
        {
            Contract.Requires <NullReferenceException>(name != null);

            PerspexProperty <TValue> result = new PerspexProperty <TValue>(
                typeof(TOwner) + "." + name,
                typeof(TOwner),
                defaultValue,
                inherits,
                defaultBindingMode);

            PerspexObject.Register(typeof(THost), result);

            return(result);
        }
コード例 #20
0
        /// <summary>
        /// Gets an observable for a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <returns></returns>
        public IObservable <Tuple <T, T> > GetObservableWithHistory <T>(PerspexProperty <T> property)
        {
            return(Observable.Create <Tuple <T, T> >(observer =>
            {
                EventHandler <PerspexPropertyChangedEventArgs> handler = (s, e) =>
                {
                    if (e.Property == property)
                    {
                        observer.OnNext(Tuple.Create((T)e.OldValue, (T)e.NewValue));
                    }
                };

                this.PropertyChanged += handler;

                return () =>
                {
                    this.PropertyChanged -= handler;
                };
            }));
        }
コード例 #21
0
        /// <summary>
        /// Checks whether a <see cref="PerspexProperty"/> is registered on this class.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>True if the property is registered, otherwise false.</returns>
        private bool IsRegistered(PerspexProperty property)
        {
            Type type = this.GetType();

            while (type != null)
            {
                List <PerspexProperty> list;

                if (registered.TryGetValue(type, out list))
                {
                    if (list.Contains(property))
                    {
                        return(true);
                    }
                }

                type = type.GetTypeInfo().BaseType;
            }

            return(false);
        }
コード例 #22
0
        /// <summary>
        /// Finds a <see cref="PerspexProperty"/> registered on a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="property">The property.</param>
        /// <returns>The registered property or null if not found.</returns>
        /// <remarks>
        /// Calling AddOwner on a PerspexProperty creates a new PerspexProperty that is a
        /// different object but is equal according to <see cref="object.Equals(object)"/>.
        /// </remarks>
        public PerspexProperty FindRegistered(Type type, PerspexProperty property)
        {
            while (type != null)
            {
                Dictionary <int, PerspexProperty> inner;

                if (_registered.TryGetValue(type, out inner))
                {
                    PerspexProperty result;

                    if (inner.TryGetValue(property.Id, out result))
                    {
                        return(result);
                    }
                }

                type = type.GetTypeInfo().BaseType;
            }

            return(null);
        }
コード例 #23
0
        /// <summary>
        /// Binds a property on an <see cref="IPerspexObject"/> to an <see cref="IBinding"/>.
        /// </summary>
        /// <param name="target">The object.</param>
        /// <param name="property">The property to bind.</param>
        /// <param name="binding">The 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 Bind(
            this IPerspexObject target,
            PerspexProperty property,
            IBinding binding,
            object anchor = null)
        {
            Contract.Requires <ArgumentNullException>(target != null);
            Contract.Requires <ArgumentNullException>(property != null);
            Contract.Requires <ArgumentNullException>(binding != null);

            var result = binding.Initiate(target, property, anchor);

            if (result != null)
            {
                return(BindingOperations.Apply(target, property, result, anchor));
            }
            else
            {
                return(Disposable.Empty);
            }
        }
コード例 #24
0
        /// <summary>
        /// Finds a <see cref="PerspexProperty"/> registered on a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="property">The property.</param>
        /// <returns>The registered property or null if not found.</returns>
        /// <remarks>
        /// Calling AddOwner on a PerspexProperty creates a new PerspexProperty that is a
        /// different object but is equal according to <see cref="object.Equals(object)"/>.
        /// </remarks>
        public PerspexProperty FindRegistered(Type type, PerspexProperty property)
        {
            while (type != null)
            {
                List <PerspexProperty> list;

                if (_registered.TryGetValue(type, out list))
                {
                    var index = list.IndexOf(property);

                    if (index != -1)
                    {
                        return(list[index]);
                    }
                }

                type = type.GetTypeInfo().BaseType;
            }

            return(null);
        }
コード例 #25
0
        /// <summary>
        /// Gets an observable for a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="T">The type of the property.</typeparam>
        /// <param name="property">The property.</param>
        /// <returns>An observable which when subscribed pushes the old and new values of the
        /// property each time it is changed.</returns>
        public IObservable <Tuple <T, T> > GetObservableWithHistory <T>(PerspexProperty <T> property)
        {
            return(new PerspexObservable <Tuple <T, T> >(
                       observer =>
            {
                EventHandler <PerspexPropertyChangedEventArgs> handler = (s, e) =>
                {
                    if (e.Property == property)
                    {
                        observer.OnNext(Tuple.Create((T)e.OldValue, (T)e.NewValue));
                    }
                };

                PropertyChanged += handler;

                return Disposable.Create(() =>
                {
                    PropertyChanged -= handler;
                });
            },
                       GetObservableDescription(property)));
        }
コード例 #26
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));
        }
コード例 #27
0
        /// <summary>
        /// Registers an attached <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="THost">The type of the class that the property is to be registered on.</typeparam>
        /// <typeparam name="TValue">The type of the property's value.</typeparam>
        /// <param name="name">The name of the property.</param>
        /// <param name="ownerType">The type of the class that is registering the property.</param>
        /// <param name="defaultValue">The default value of the property.</param>
        /// <param name="inherits">Whether the property inherits its value.</param>
        /// <param name="defaultBindingMode">The default binding mode for the property.</param>
        /// <param name="validate">A validation function.</param>
        /// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
        public static PerspexProperty <TValue> RegisterAttached <THost, TValue>(
            string name,
            Type ownerType,
            TValue defaultValue            = default(TValue),
            bool inherits                  = false,
            BindingMode defaultBindingMode = BindingMode.OneWay,
            Func <PerspexObject, TValue, TValue> validate = null)
        {
            Contract.Requires <NullReferenceException>(name != null);

            PerspexProperty <TValue> result = new PerspexProperty <TValue>(
                name,
                ownerType,
                defaultValue,
                inherits,
                defaultBindingMode,
                validate,
                true);

            PerspexObject.Register(typeof(THost), result);

            return(result);
        }
コード例 #28
0
        /// <summary>
        /// Gets an observable for a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>An observable.</returns>
        public IObservable <object> GetObservable(PerspexProperty property)
        {
            Contract.Requires <NullReferenceException>(property != null);

            return(Observable.Create <object>(observer =>
            {
                EventHandler <PerspexPropertyChangedEventArgs> handler = (s, e) =>
                {
                    if (e.Property == property)
                    {
                        observer.OnNext(e.NewValue);
                    }
                };

                this.PropertyChanged += handler;
                observer.OnNext(this.GetValue(property));

                return () =>
                {
                    this.PropertyChanged -= handler;
                };
            }).StartWith(this.GetValue(property)));
        }
コード例 #29
0
        /// <summary>
        /// Binds a <see cref="PerspexProperty"/> to an observable.
        /// </summary>
        /// <typeparam name="T">The type of the property.</typeparam>
        /// <param name="property">The property.</param>
        /// <param name="source">The observable.</param>
        /// <param name="priority">The priority of the binding.</param>
        /// <returns>
        /// A disposable which can be used to terminate the binding.
        /// </returns>
        public IDisposable Bind <T>(
            PerspexProperty <T> property,
            IObservable <T> source,
            BindingPriority priority = BindingPriority.LocalValue)
        {
            Contract.Requires <ArgumentNullException>(property != null);
            VerifyAccess();
            if (property.IsDirect)
            {
                property = (PerspexProperty <T>)GetRegistered(property);

                if (property.Setter == null)
                {
                    throw new ArgumentException($"The property {property.Name} is readonly.");
                }

                return(source.Subscribe(x => SetValue(property, x)));
            }
            else
            {
                return(Bind((PerspexProperty)property, source.Select(x => (object)x), priority));
            }
        }
コード例 #30
0
        /// <summary>
        /// Registers a <see cref="PerspexProperty"/>.
        /// </summary>
        /// <typeparam name="TOwner">The type of the class that is registering the property.</typeparam>
        /// <typeparam name="TValue">The type of the property's value.</typeparam>
        /// <param name="name">The name of the property.</param>
        /// <param name="defaultValue">The default value of the property.</param>
        /// <param name="inherits">Whether the property inherits its value.</param>
        /// <param name="defaultBindingMode">The default binding mode for the property.</param>
        /// <param name="validate">A validation function.</param>
        /// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
        public static PerspexProperty <TValue> Register <TOwner, TValue>(
            string name,
            TValue defaultValue                    = default(TValue),
            bool inherits                          = false,
            BindingMode defaultBindingMode         = BindingMode.OneWay,
            Func <TOwner, TValue, TValue> validate = null)
            where TOwner : PerspexObject
        {
            Contract.Requires <NullReferenceException>(name != null);

            PerspexProperty <TValue> result = new PerspexProperty <TValue>(
                name,
                typeof(TOwner),
                defaultValue,
                inherits,
                defaultBindingMode,
                Cast(validate),
                false);

            PerspexObject.Register(typeof(TOwner), result);

            return(result);
        }