예제 #1
0
        /// <inheritdoc/>
        public InstancedBinding Initiate(
            IAvaloniaObject target,
            AvaloniaProperty targetProperty,
            object anchor = null)
        {
            if (Name == "Red")
            {
            }

            var host = (target as IControl) ?? (anchor as IControl);
            var style = anchor as IStyle;
            var resource = AvaloniaProperty.UnsetValue;

            if (host != null)
            {
                resource = host.FindStyleResource(Name);
            }
            else if (style != null)
            {
                resource = style.FindResource(Name);
            }

            if (resource != AvaloniaProperty.UnsetValue)
            {
                return new InstancedBinding(resource, Priority);
            }
            else
            {
                return null;
            }
        }
 public AvaloniaPropertyChangedEventArgs(
     IAvaloniaObject sender,
     BindingPriority priority)
 {
     Sender   = sender;
     Priority = priority;
     IsEffectiveValueChange = true;
 }
예제 #3
0
 /// <summary>
 /// Sets the <see cref="BehaviorCollection"/> associated with a specified object.
 /// </summary>
 /// <param name="obj">The <see cref="IAvaloniaObject"/> on which to set the <see cref="BehaviorCollection"/>.</param>
 /// <param name="value">The <see cref="BehaviorCollection"/> associated with the object.</param>
 public static void SetBehaviors(IAvaloniaObject obj, BehaviorCollection?value)
 {
     if (obj == null)
     {
         throw new ArgumentNullException(nameof(obj));
     }
     obj.SetValue(BehaviorsProperty, value);
 }
예제 #4
0
 private static void SetContentProperty(IAvaloniaObject targetLocation, object?view)
 {
     if (view != null && targetLocation != null)
     {
         Type?type = targetLocation.GetType();
         type.GetProperty("Content")?.SetValue(targetLocation, view);
     }
 }
 public InstancedBinding?Initiate(
     IAvaloniaObject target,
     AvaloniaProperty?targetProperty,
     object?anchor             = null,
     bool enableDataValidation = false)
 {
     return(new InstancedBinding(Source.GetSubject(Property), Mode, BindingPriority.LocalValue));
 }
예제 #6
0
 public InstancedBinding Initiate(
     IAvaloniaObject target,
     AvaloniaProperty targetProperty,
     object anchor             = null,
     bool enableDataValidation = false)
 {
     return(new InstancedBinding(_source));
 }
예제 #7
0
 private static byte?CoerceBlue(IAvaloniaObject arg1, byte?arg2)
 {
     if (arg2 is null)
     {
         return(null);
     }
     return(ColorPickerHelpers.Clamp(arg2.Value, 0, 255));
 }
예제 #8
0
        /// <inheritdoc/>
        void IDirectPropertyAccessor.SetValue(IAvaloniaObject instance, object value)
        {
            if (Setter == null)
            {
                throw new ArgumentException($"The property {Name} is readonly.");
            }

            Setter((TOwner)instance, (TValue)value);
        }
예제 #9
0
        /// <summary>
        /// Coerces/validates the <see cref="HsvColor"/> property value.
        /// </summary>
        /// <param name="instance">The <see cref="ColorView"/> instance.</param>
        /// <param name="value">The value to coerce.</param>
        /// <returns>The coerced/validated value.</returns>
        private static HsvColor CoerceHsvColor(IAvaloniaObject instance, HsvColor value)
        {
            if (instance is ColorView colorView)
            {
                return(colorView.OnCoerceHsvColor(value));
            }

            return(value);
        }
예제 #10
0
 public IndexerBinding(
     IAvaloniaObject source,
     AvaloniaProperty property,
     BindingMode mode)
 {
     Source = source;
     Property = property;
     Mode = mode;
 }
예제 #11
0
        private static string OnEventNameChange(IAvaloniaObject element, string routedEvent)
        {
            if (element != null && element is Interactive interactive)
            {
                UpdateConnection(interactive, routedEvent, GetCommand(interactive));
            }

            return(routedEvent);
        }
 public TypedBindingAdapter(
     IAvaloniaObject target,
     AvaloniaProperty <T> property,
     IObservable <BindingValue <object?> > source)
 {
     _target   = target;
     _property = property;
     _source   = source;
 }
예제 #13
0
        /// <summary>
        /// Gets an observable for a <see cref="AvaloniaProperty"/>.
        /// </summary>
        /// <param name="o">The object.</param>
        /// <param name="property">The property.</param>
        /// <returns>
        /// An observable which fires immediately with the current value of the property on the
        /// object and subsequently each time the property value changes.
        /// </returns>
        /// <remarks>
        /// The subscription to <paramref name="o"/> is created using a weak reference.
        /// </remarks>
        public static IObservable <BindingValue <object> > GetBindingObservable(
            this IAvaloniaObject o,
            AvaloniaProperty property)
        {
            Contract.Requires <ArgumentNullException>(o != null);
            Contract.Requires <ArgumentNullException>(property != null);

            return(new AvaloniaPropertyBindingObservable <object>(o, property));
        }
예제 #14
0
        /// <summary>
        /// Gets an observable that listens for property changed events for an
        /// <see cref="AvaloniaProperty"/>.
        /// </summary>
        /// <param name="o">The object.</param>
        /// <param name="property">The property.</param>
        /// <returns>
        /// An observable which when subscribed pushes the property changed event args
        /// each time a <see cref="IAvaloniaObject.PropertyChanged"/> event is raised
        /// for the specified property.
        /// </returns>
        public static IObservable <AvaloniaPropertyChangedEventArgs> GetPropertyChangedObservable(
            this IAvaloniaObject o,
            AvaloniaProperty property)
        {
            Contract.Requires <ArgumentNullException>(o != null);
            Contract.Requires <ArgumentNullException>(property != null);

            return(new AvaloniaPropertyChangedObservable(o, property));
        }
 public static IObservable <BindingValue <T> > Create(
     IAvaloniaObject target,
     AvaloniaProperty <T> property,
     IObservable <BindingValue <object?> > source)
 {
     return(source is IObservable <BindingValue <T> > result ?
            result :
            new TypedBindingAdapter <T>(target, property, source));
 }
예제 #16
0
        /// <summary>
        /// Gets the value of the RegionName attached property.
        /// </summary>
        /// <param name="element">The target element.</param>
        /// <returns>The <see cref="IRegionManager"/> attached to the <paramref name="element"/> element.</returns>
        public IRegionManager GetRegionManager(IAvaloniaObject element)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            return(element.GetValue(RegionManager.RegionManagerProperty) as IRegionManager);
        }
예제 #17
0
        private static double OnCoerceIncrement(IAvaloniaObject instance, double value)
        {
            if (instance is NumericUpDown upDown)
            {
                return(upDown.OnCoerceIncrement(value));
            }

            return(value);
        }
예제 #18
0
        /// <inheritdoc/>
        internal override IDisposable RouteBind(
            IAvaloniaObject o,
            IObservable <BindingValue <object?> > source,
            BindingPriority priority)
        {
            var adapter = TypedBindingAdapter <TValue> .Create(o, this, source);

            return(o.Bind <TValue>(this, adapter, priority));
        }
예제 #19
0
 /// <summary>
 /// Gets a subject for a <see cref="AvaloniaProperty"/>.
 /// </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 IAvaloniaObject o,
     AvaloniaProperty <T> property,
     BindingPriority priority = BindingPriority.LocalValue)
 {
     return(Subject.Create <T>(
                Observer.Create <T>(x => o.SetValue(property, x, priority)),
                o.GetObservable(property)));
 }
예제 #20
0
        /// <summary>
        /// Sets the <see cref="RegionManagerProperty"/> attached property.
        /// </summary>
        /// <param name="target">The target element.</param>
        /// <param name="value">The value.</param>
        public static void SetRegionManager(IAvaloniaObject target, IRegionManager value)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            target.SetValue(RegionManagerProperty, value);
        }
예제 #21
0
        private static void StyledPropertyChanged(IAvaloniaObject dependencyObject, AvaloniaPropertyChangedEventArgs args)
        {
            ItemMetadata itemMetadata = dependencyObject as ItemMetadata;

            if (itemMetadata != null)
            {
                itemMetadata.InvokeMetadataChanged();
            }
        }
예제 #22
0
        private static ICommand OnCommandChange(IAvaloniaObject element, ICommand commandValue)
        {
            if (element != null && element is Interactive interactive)
            {
                UpdateConnection(interactive, GetEventName(interactive), commandValue);
            }

            return(commandValue);
        }
예제 #23
0
        /// <summary>
        /// Gets the value of the <see cref="RegionNameProperty"/> attached property.
        /// </summary>
        /// <param name="target">The target element.</param>
        /// <returns>The <see cref="IRegionManager"/> attached to the <paramref name="target"/> element.</returns>
        public static IRegionManager GetRegionManager(IAvaloniaObject target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            return((IRegionManager)target.GetValue(RegionManagerProperty));
        }
예제 #24
0
 public IndexerBinding(
     IAvaloniaObject source,
     AvaloniaProperty property,
     BindingMode mode)
 {
     Source   = source;
     Property = property;
     Mode     = mode;
 }
예제 #25
0
        /// <summary>
        /// Gets the value for the RegionName attached property.
        /// </summary>
        /// <param name="element">The object to adapt. This is typically a container (i.e a control).</param>
        /// <returns>The name of the region that should be created when
        /// the RegionManager is also set in this element.</returns>
        public string GetRegionName(IAvaloniaObject element)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            return(element.GetValue(RegionManager.RegionNameProperty) as string);
        }
예제 #26
0
 public PriorityValue(
     IAvaloniaObject owner,
     StyledPropertyBase <T> property,
     IValueSink sink,
     LocalValueEntry <T> existing)
     : this(owner, property, sink)
 {
     _value   = _localValue = existing.GetValue(BindingPriority.LocalValue);
     Priority = BindingPriority.LocalValue;
 }
예제 #27
0
        private static void ValueChangedCallback(IAvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
        {
            ObservableObject <T>        thisInstance = ((ObservableObject <T>)d);
            PropertyChangedEventHandler eventHandler = thisInstance.PropertyChanged;

            if (eventHandler != null)
            {
                eventHandler(thisInstance, new PropertyChangedEventArgs(nameof(Value)));
            }
        }
예제 #28
0
 public LogicalTreeNode(IAvaloniaObject avaloniaObject, TreeNode?parent)
     : base(avaloniaObject, parent)
 {
     Children = avaloniaObject switch
     {
         ILogical logical => new LogicalTreeNodeCollection(this, logical),
         Controls.Application host => new ApplicationHostLogical(this, host),
         _ => TreeNodeCollection.Empty
     };
 }
예제 #29
0
        /// <summary>
        /// Gets a weak observable for a <see cref="AvaloniaProperty"/>.
        /// </summary>
        /// <param name="o">The object.</param>
        /// <param name="property">The property.</param>
        /// <returns>An observable.</returns>
        public static IObservable <object> GetWeakObservable(this IAvaloniaObject o, AvaloniaProperty property)
        {
            Contract.Requires <ArgumentNullException>(o != null);
            Contract.Requires <ArgumentNullException>(property != null);

            return(new WeakPropertyChangedObservable(
                       new WeakReference <IAvaloniaObject>(o),
                       property,
                       GetDescription(o, property)));
        }
        /// <summary>
        /// Applies an <see cref="InstancedBinding"/> a property on an <see cref="IAvaloniaObject"/>.
        /// </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 provide this context.
        /// </param>
        /// <returns>An <see cref="IDisposable"/> which can be used to cancel the binding.</returns>
        public static IDisposable Apply(
            IAvaloniaObject target,
            AvaloniaProperty 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
                           .Where(x => BindingNotification.ExtractValue(x) != AvaloniaProperty.UnsetValue)
                           .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(Observable.CombineLatest(
                           binding.Observable,
                           target.GetObservable(property),
                           (_, v) => v)
                       .Subscribe(x => binding.Subject.OnNext(x)));

            default:
                throw new ArgumentException("Invalid binding mode.");
            }
        }
예제 #31
0
        public TValue CoerceValue(IAvaloniaObject instance, TValue baseValue)
        {
            var metadata = GetMetadata(instance.GetType());

            if (metadata.CoerceValue != null)
            {
                return(metadata.CoerceValue.Invoke(instance, baseValue));
            }

            return(baseValue);
        }
예제 #32
0
        /// <inheritdoc/>
        internal override void InvokeSetter(IAvaloniaObject instance, BindingValue <TValue> value)
        {
            if (Setter == null)
            {
                throw new ArgumentException($"The property {Name} is readonly.");
            }

            if (value.HasValue)
            {
                Setter((TOwner)instance, value.Value);
            }
        }
예제 #33
0
        public InstancedBinding Initiate(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor = null)
        {
            var mode = Mode == BindingMode.Default ?
                targetProperty.GetMetadata(target.GetType()).DefaultBindingMode :
                Mode;

            if (mode == BindingMode.TwoWay)
            {
                return new InstancedBinding(Source.GetSubject(Property), mode);
            }
            else
            {
                return new InstancedBinding(Source.GetObservable(Property), mode);
            }
        }
예제 #34
0
        /// <summary>
        /// Applies an <see cref="InstancedBinding"/> a property on an <see cref="IAvaloniaObject"/>.
        /// </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(
            IAvaloniaObject target,
            AvaloniaProperty 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
                            .Where(x => BindingNotification.ExtractValue(x) != AvaloniaProperty.UnsetValue)
                            .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.");
            }
        }
예제 #35
0
        /// <inheritdoc/>
        public InstancedBinding Initiate(
            IAvaloniaObject target,
            AvaloniaProperty targetProperty,
            object anchor = null)
        {
            if (Converter == null)
            {
                throw new NotSupportedException("MultiBinding without Converter not currently supported.");
            }

            var targetType = targetProperty?.PropertyType ?? typeof(object);
            var result = new BehaviorSubject<object>(AvaloniaProperty.UnsetValue);
            var children = Bindings.Select(x => x.Initiate(target, null));
            var input = children.Select(x => x.Subject).CombineLatest().Select(x => ConvertValue(x, targetType));
            input.Subscribe(result);
            return new InstancedBinding(result, Mode, Priority);
        }
예제 #36
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(IAvaloniaObject target, AvaloniaProperty 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;
            }
        }
예제 #37
0
 private IObservable<object> GetParentDataContext(IAvaloniaObject target)
 {
     // The DataContext is based on the visual parent and not the logical parent: this may
     // seem unintuitive considering the fact that property inheritance works on the logical
     // tree, but consider a ContentControl with a ContentPresenter. The ContentControl's
     // Content property is bound to a value which becomes the ContentPresenter's 
     // DataContext - it is from this that the child hosted by the ContentPresenter needs to
     // inherit its DataContext.
     return target.GetObservable(Visual.VisualParentProperty)
         .Select(x =>
         {
             return (x as IAvaloniaObject)?.GetObservable(Control.DataContextProperty) ?? 
                    Observable.Return((object)null);
         }).Switch();
 }
예제 #38
0
        private ExpressionObserver CreateTemplatedParentObserver(
            IAvaloniaObject 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;
        }
예제 #39
0
        /// <inheritdoc/>
        public InstancedBinding Initiate(
            IAvaloniaObject target,
            AvaloniaProperty targetProperty,
            object anchor = null)
        {
            Contract.Requires<ArgumentNullException>(target != null);

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

            ExpressionObserver observer;

            if (pathInfo.ElementName != null || ElementName != null)
            {
                observer = CreateElementObserver(
                    (target as IControl) ?? (anchor as IControl),
                    pathInfo.ElementName ?? ElementName,
                    pathInfo.Path);
            }
            else if (Source != null)
            {
                observer = CreateSourceObserver(Source, pathInfo.Path);
            }
            else if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
            {
                observer = CreateDataContexObserver(
                    target,
                    pathInfo.Path,
                    targetProperty == Control.DataContextProperty,
                    anchor);
            }
            else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
            {
                observer = CreateTemplatedParentObserver(target, pathInfo.Path);
            }
            else
            {
                throw new NotSupportedException();
            }

            var fallback = FallbackValue;

            // If we're binding to DataContext and our fallback is UnsetValue then override
            // the fallback value to null, as broken bindings to DataContext must reset the
            // DataContext in order to not propagate incorrect DataContexts to child controls.
            // See Avalonia.Markup.Xaml.UnitTests.Data.DataContext_Binding_Should_Produce_Correct_Results.
            if (targetProperty == Control.DataContextProperty && fallback == AvaloniaProperty.UnsetValue)
            {
                fallback = null;
            }

            var subject = new ExpressionSubject(
                observer,
                targetProperty?.PropertyType ?? typeof(object),
                fallback,
                Converter ?? DefaultValueConverter.Instance,
                ConverterParameter,
                Priority);

            return new InstancedBinding(subject, Mode, Priority);
        }
예제 #40
0
		private static void somethingChanged(IAvaloniaObject dependencyObject, bool changed)
		{
			if (changed)
			{
				((ViewModelViewHost) dependencyObject).updateViewModel.OnNext(Unit.Default);
			}
		}
예제 #41
0
        private ExpressionObserver CreateDataContexObserver(
            IAvaloniaObject target,
            string path,
            bool targetIsDataContext,
            object anchor)
        {
            Contract.Requires<ArgumentNullException>(target != null);

            if (!(target is IControl))
            {
                target = anchor as IControl;

                if (target == null)
                {
                    throw new InvalidOperationException("Cannot find a DataContext to bind to.");
                }
            }

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

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