/// <inheritdoc/> public InstancedBinding Initiate( IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor = null, bool enableDataValidation = false) { if (Converter == null) { throw new NotSupportedException("MultiBinding without Converter not currently supported."); } var targetType = targetProperty?.PropertyType ?? typeof(object); var children = Bindings.Select(x => x.Initiate(target, null)); var input = children.Select(x => x.Subject).CombineLatest().Select(x => ConvertValue(x, targetType)); var mode = Mode == BindingMode.Default ? targetProperty.GetMetadata(target.GetType()).DefaultBindingMode : Mode; switch (mode) { case BindingMode.OneTime: return(InstancedBinding.OneTime(input, Priority)); case BindingMode.OneWay: return(InstancedBinding.OneWay(input, Priority)); default: throw new NotSupportedException( "MultiBinding currently only supports OneTime and OneWay BindingMode."); } }
public InstancedBinding Initiate( IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor = null, bool enableDataValidation = false) { var mode = Mode == BindingMode.Default ? targetProperty.GetMetadata(target.GetType()).DefaultBindingMode : Mode; switch (mode) { case BindingMode.OneTime: return(InstancedBinding.OneTime(Source.GetObservable(Property))); case BindingMode.OneWay: return(InstancedBinding.OneWay(Source.GetObservable(Property))); case BindingMode.OneWayToSource: return(InstancedBinding.OneWayToSource(Source.GetSubject(Property))); case BindingMode.TwoWay: return(InstancedBinding.TwoWay(Source.GetSubject(Property))); default: throw new NotSupportedException("Unsupported BindingMode."); } }
/// <summary> /// Finds a registered property on an object by name. /// </summary> /// <param name="o">The object.</param> /// <param name="name">The property name.</param> /// <returns> /// The registered property or null if no matching property found. /// </returns> /// <exception cref="InvalidOperationException"> /// The property name contains a '.'. /// </exception> public AvaloniaProperty?FindRegistered(IAvaloniaObject o, string name) { _ = o ?? throw new ArgumentNullException(nameof(o)); _ = name ?? throw new ArgumentNullException(nameof(name)); return(FindRegistered(o.GetType(), name)); }
/// <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; } }
/// <summary> /// Binds a property on an <see cref="IAvaloniaObject"/> 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 IAvaloniaObject target, AvaloniaProperty property, IBinding binding, object anchor = null) { Contract.Requires <ArgumentNullException>(target != null); Contract.Requires <ArgumentNullException>(property != null); Contract.Requires <ArgumentNullException>(binding != null); var metadata = property.GetMetadata(target.GetType()) as IDirectPropertyMetadata; var result = binding.Initiate( target, property, anchor, metadata?.EnableDataValidation ?? false); if (result != null) { return(BindingOperations.Apply(target, property, result, anchor)); } else { return(Disposable.Empty); } }
/// <summary> /// Finds a registered property on an object by name. /// </summary> /// <param name="o">The object.</param> /// <param name="name">The property name.</param> /// <returns> /// The registered property or null if no matching property found. /// </returns> /// <exception cref="InvalidOperationException"> /// The property name contains a '.'. /// </exception> public AvaloniaProperty FindRegistered(IAvaloniaObject o, string name) { Contract.Requires <ArgumentNullException>(o != null); Contract.Requires <ArgumentNullException>(name != null); return(FindRegistered(o.GetType(), name)); }
private static void SetContentProperty(IAvaloniaObject targetLocation, object?view) { if (view != null && targetLocation != null) { Type?type = targetLocation.GetType(); type.GetProperty("Content")?.SetValue(targetLocation, view); } }
/// <summary> /// Finds a direct property as registered on an object. /// </summary> /// <param name="o">The object.</param> /// <param name="property">The direct property.</param> /// <returns> /// The registered property or null if no matching property found. /// </returns> public DirectPropertyBase <T> FindRegisteredDirect <T>( IAvaloniaObject o, DirectPropertyBase <T> property) { if (property.Owner == o.GetType()) { return(property); } foreach (var p in GetRegisteredDirect(o.GetType())) { if (p == property) { return((DirectPropertyBase <T>)p); } } return(null); }
/// <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."); } }
public TValue CoerceValue(IAvaloniaObject instance, TValue baseValue) { var metadata = GetMetadata(instance.GetType()); if (metadata.CoerceValue != null) { return(metadata.CoerceValue.Invoke(instance, baseValue)); } return(baseValue); }
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)); } }
/// <summary> /// Finds a direct property as registered on an object. /// </summary> /// <param name="o">The object.</param> /// <param name="property">The direct property.</param> /// <returns> /// The registered property or null if no matching property found. /// </returns> public DirectPropertyBase <T>?FindRegisteredDirect <T>( IAvaloniaObject o, DirectPropertyBase <T> property) { if (property.Owner == o.GetType()) { return(property); } var registeredDirect = GetRegisteredDirect(o.GetType()); var registeredDirectCount = registeredDirect.Count; for (var i = 0; i < registeredDirectCount; i++) { var p = registeredDirect[i]; if (p == property) { return((DirectPropertyBase <T>)p); } } return(null); }
public PriorityValue( IAvaloniaObject owner, StyledPropertyBase <T> property, IValueSink sink) { _owner = owner; Property = property; _sink = sink; if (property.HasCoercion) { var metadata = property.GetMetadata(owner.GetType()); _coerceValue = metadata.CoerceValue; } }
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); } }
/// <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."); } }
/// <inheritdoc/> public InstancedBinding?Initiate( IAvaloniaObject target, AvaloniaProperty?targetProperty, object?anchor = null, bool enableDataValidation = false) { var targetType = targetProperty?.PropertyType ?? typeof(object); var converter = Converter; // We only respect `StringFormat` if the type of the property we're assigning to will // accept a string. Note that this is slightly different to WPF in that WPF only applies // `StringFormat` for target type `string` (not `object`). if (!string.IsNullOrWhiteSpace(StringFormat) && (targetType == typeof(string) || targetType == typeof(object))) { converter = new StringFormatMultiValueConverter(StringFormat !, converter); } var children = Bindings.Select(x => x.Initiate(target, null)); var input = children.Select(x => x?.Observable !) .Where(x => x is not null) .CombineLatest() .Select(x => ConvertValue(x, targetType, converter)) .Where(x => x != BindingOperations.DoNothing); var mode = Mode == BindingMode.Default ? targetProperty?.GetMetadata(target.GetType()).DefaultBindingMode : Mode; switch (mode) { case BindingMode.OneTime: return(InstancedBinding.OneTime(input, Priority)); case BindingMode.OneWay: return(InstancedBinding.OneWay(input, Priority)); default: throw new NotSupportedException( "MultiBinding currently only supports OneTime and OneWay BindingMode."); } }
/// <summary> /// Method that will create the region, by calling the right <see cref="IRegionAdapter"/>. /// </summary> /// <param name="targetElement">The target element that will host the <see cref="IRegion"/>.</param> /// <param name="regionName">Name of the region.</param> /// <returns>The created <see cref="IRegion"/></returns> protected virtual IRegion CreateRegion(IAvaloniaObject targetElement, string regionName) { if (targetElement == null) { throw new ArgumentNullException(nameof(targetElement)); } try { // Build the region IRegionAdapter regionAdapter = this.regionAdapterMappings.GetMapping(targetElement.GetType()); IRegion region = regionAdapter.Initialize(targetElement, regionName); return(region); } catch (Exception ex) { throw new RegionCreationException(string.Format(CultureInfo.CurrentCulture, Resources.RegionCreationException, regionName, ex), ex); } }
private void UpdateValue(BindingValue <T> value) { if (value.HasValue && Property.ValidateValue?.Invoke(value.Value) == false) { value = Property.GetDefaultValue(_owner.GetType()); } if (value.Type == BindingValueType.DoNothing) { return; } var old = Value; if (value.Type != BindingValueType.DataValidationError) { Value = value.ToOptional(); } _sink.ValueChanged(Property, Priority, old, value); }
protected TreeNode(IAvaloniaObject avaloniaObject, TreeNode?parent, string?customName = null) { _classes = string.Empty; Parent = parent; var visual = avaloniaObject; Type = customName ?? avaloniaObject.GetType().Name; Visual = visual !; FontWeight = IsRoot ? FontWeight.Bold : FontWeight.Normal; if (visual is IControl control) { ElementName = control.Name; var removed = Observable.FromEventPattern <LogicalTreeAttachmentEventArgs>( x => control.DetachedFromLogicalTree += x, x => control.DetachedFromLogicalTree -= x); var classesChanged = Observable.FromEventPattern < NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>( x => control.Classes.CollectionChanged += x, x => control.Classes.CollectionChanged -= x) .TakeUntil(removed); _classesSubscription = classesChanged.Select(_ => Unit.Default) .StartWith(Unit.Default) .Subscribe(_ => { if (control.Classes.Count > 0) { Classes = "(" + string.Join(" ", control.Classes) + ")"; } else { Classes = string.Empty; } }); } }
/// <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; } }
/// <summary> /// Gets all <see cref="AvaloniaProperty"/>s registered on a object. /// </summary> /// <param name="o">The object.</param> /// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns> public IReadOnlyList <AvaloniaProperty> GetRegistered(IAvaloniaObject o) { Contract.Requires <ArgumentNullException>(o != null); return(GetRegistered(o.GetType())); }
/// <summary> /// Gets all <see cref="AvaloniaProperty"/>s registered on a object. /// </summary> /// <param name="o">The object.</param> /// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns> public IReadOnlyList <AvaloniaProperty> GetRegistered(IAvaloniaObject o) { _ = o ?? throw new ArgumentNullException(nameof(o)); return(GetRegistered(o.GetType())); }
/// <summary> /// Gets a description of a property that van be used in observables. /// </summary> /// <param name="o">The object.</param> /// <param name="property">The property</param> /// <returns>The description.</returns> private static string GetDescription(IAvaloniaObject o, AvaloniaProperty property) { return($"{o.GetType().Name}.{property.Name}"); }
/// <summary> /// Gets a direct property as registered on an object. /// </summary> /// <param name="o">The object.</param> /// <param name="property">The direct property.</param> /// <returns> /// The registered. /// </returns> public DirectPropertyBase <T> GetRegisteredDirect <T>( IAvaloniaObject o, DirectPropertyBase <T> property) { return(FindRegisteredDirect(o, property) ?? throw new ArgumentException($"Property '{property.Name} not registered on '{o.GetType()}")); }
/// <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) { _ = target ?? throw new ArgumentNullException(nameof(target)); _ = property ?? throw new ArgumentNullException(nameof(property)); _ = binding ?? throw new ArgumentNullException(nameof(binding)); var mode = binding.Mode; if (mode == BindingMode.Default) { mode = property.GetMetadata(target.GetType()).DefaultBindingMode; } switch (mode) { case BindingMode.Default: case BindingMode.OneWay: if (binding.Observable is null) { throw new InvalidOperationException("InstancedBinding does not contain an observable."); } return(target.Bind(property, binding.Observable, binding.Priority)); case BindingMode.TwoWay: if (binding.Subject is null) { throw new InvalidOperationException("InstancedBinding does not contain a subject."); } return(new TwoWayBindingDisposable( 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) { // Perf: Avoid allocating closure in the outer scope. var targetCopy = target; var propertyCopy = property; var bindingCopy = binding; return(source .Where(x => BindingNotification.ExtractValue(x) != AvaloniaProperty.UnsetValue) .Take(1) .Subscribe(x => targetCopy.SetValue( propertyCopy, BindingNotification.ExtractValue(x), bindingCopy.Priority))); } else { target.SetValue(property, binding.Value, binding.Priority); return(Disposable.Empty); } case BindingMode.OneWayToSource: { if (binding.Observable is null) { throw new InvalidOperationException("InstancedBinding does not contain an observable."); } if (binding.Subject is null) { throw new InvalidOperationException("InstancedBinding does not contain a subject."); } // Perf: Avoid allocating closure in the outer scope. var bindingCopy = binding; return(Observable.CombineLatest( binding.Observable, target.GetObservable(property), (_, v) => v) .Subscribe(x => bindingCopy.Subject.OnNext(x))); } default: throw new ArgumentException("Invalid binding mode."); } }