summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/VisualElement.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core/VisualElement.cs')
-rw-r--r--Xamarin.Forms.Core/VisualElement.cs764
1 files changed, 764 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/VisualElement.cs b/Xamarin.Forms.Core/VisualElement.cs
new file mode 100644
index 00000000..16efe730
--- /dev/null
+++ b/Xamarin.Forms.Core/VisualElement.cs
@@ -0,0 +1,764 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public partial class VisualElement : Element, IAnimatable, IVisualElementController, IResourcesProvider
+ {
+ internal static readonly BindablePropertyKey NavigationPropertyKey = BindableProperty.CreateReadOnly("Navigation", typeof(INavigation), typeof(VisualElement), default(INavigation));
+
+ public static readonly BindableProperty NavigationProperty = NavigationPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty InputTransparentProperty = BindableProperty.Create("InputTransparent", typeof(bool), typeof(VisualElement), default(bool));
+
+ public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create("IsEnabled", typeof(bool), typeof(VisualElement), true);
+
+ static readonly BindablePropertyKey XPropertyKey = BindableProperty.CreateReadOnly("X", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty XProperty = XPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey YPropertyKey = BindableProperty.CreateReadOnly("Y", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty YProperty = YPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty AnchorXProperty = BindableProperty.Create("AnchorX", typeof(double), typeof(VisualElement), .5d);
+
+ public static readonly BindableProperty AnchorYProperty = BindableProperty.Create("AnchorY", typeof(double), typeof(VisualElement), .5d);
+
+ public static readonly BindableProperty TranslationXProperty = BindableProperty.Create("TranslationX", typeof(double), typeof(VisualElement), 0d);
+
+ public static readonly BindableProperty TranslationYProperty = BindableProperty.Create("TranslationY", typeof(double), typeof(VisualElement), 0d);
+
+ static readonly BindablePropertyKey WidthPropertyKey = BindableProperty.CreateReadOnly("Width", typeof(double), typeof(VisualElement), -1d,
+ coerceValue: (bindable, value) => double.IsNaN((double)value) ? 0d : value);
+
+ public static readonly BindableProperty WidthProperty = WidthPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey HeightPropertyKey = BindableProperty.CreateReadOnly("Height", typeof(double), typeof(VisualElement), -1d,
+ coerceValue: (bindable, value) => double.IsNaN((double)value) ? 0d : value);
+
+ public static readonly BindableProperty HeightProperty = HeightPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty RotationProperty = BindableProperty.Create("Rotation", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty RotationXProperty = BindableProperty.Create("RotationX", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty RotationYProperty = BindableProperty.Create("RotationY", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty ScaleProperty = BindableProperty.Create("Scale", typeof(double), typeof(VisualElement), 1d);
+
+ public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create("IsVisible", typeof(bool), typeof(VisualElement), true,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable).OnIsVisibleChanged((bool)oldvalue, (bool)newvalue));
+
+ public static readonly BindableProperty OpacityProperty = BindableProperty.Create("Opacity", typeof(double), typeof(VisualElement), 1d, coerceValue: (bindable, value) => ((double)value).Clamp(0, 1));
+
+ public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create("BackgroundColor", typeof(Color), typeof(VisualElement), Color.Default);
+
+ internal static readonly BindablePropertyKey BehaviorsPropertyKey = BindableProperty.CreateReadOnly("Behaviors", typeof(IList<Behavior>), typeof(VisualElement), default(IList<Behavior>),
+ defaultValueCreator: bindable =>
+ {
+ var collection = new AttachedCollection<Behavior>();
+ collection.AttachTo(bindable);
+ return collection;
+ });
+
+ public static readonly BindableProperty BehaviorsProperty = BehaviorsPropertyKey.BindableProperty;
+
+ internal static readonly BindablePropertyKey TriggersPropertyKey = BindableProperty.CreateReadOnly("Triggers", typeof(IList<TriggerBase>), typeof(VisualElement), default(IList<TriggerBase>),
+ defaultValueCreator: bindable =>
+ {
+ var collection = new AttachedCollection<TriggerBase>();
+ collection.AttachTo(bindable);
+ return collection;
+ });
+
+ public static readonly BindableProperty TriggersProperty = TriggersPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty StyleProperty = BindableProperty.Create("Style", typeof(Style), typeof(VisualElement), default(Style),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.Style = (Style)newvalue);
+
+ public static readonly BindableProperty WidthRequestProperty = BindableProperty.Create("WidthRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ public static readonly BindableProperty HeightRequestProperty = BindableProperty.Create("HeightRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ public static readonly BindableProperty MinimumWidthRequestProperty = BindableProperty.Create("MinimumWidthRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ public static readonly BindableProperty MinimumHeightRequestProperty = BindableProperty.Create("MinimumHeightRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ internal static readonly BindablePropertyKey IsFocusedPropertyKey = BindableProperty.CreateReadOnly("IsFocused", typeof(bool), typeof(VisualElement), default(bool),
+ propertyChanged: OnIsFocusedPropertyChanged);
+
+ public static readonly BindableProperty IsFocusedProperty = IsFocusedPropertyKey.BindableProperty;
+
+ readonly Dictionary<Size, SizeRequest> _measureCache = new Dictionary<Size, SizeRequest>();
+
+ readonly MergedStyle _mergedStyle;
+
+ int _batched;
+ LayoutConstraint _computedConstraint;
+
+ bool _isInNativeLayout;
+
+ bool _isNativeStateConsistent = true;
+
+ bool _isPlatformEnabled;
+
+ double _mockHeight = -1;
+
+ double _mockWidth = -1;
+
+ double _mockX = -1;
+
+ double _mockY = -1;
+
+ ResourceDictionary _resources;
+ LayoutConstraint _selfConstraint;
+
+ internal VisualElement()
+ {
+ Navigation = new NavigationProxy();
+ _mergedStyle = new MergedStyle(GetType(), this);
+ }
+
+ public double AnchorX
+ {
+ get { return (double)GetValue(AnchorXProperty); }
+ set { SetValue(AnchorXProperty, value); }
+ }
+
+ public double AnchorY
+ {
+ get { return (double)GetValue(AnchorYProperty); }
+ set { SetValue(AnchorYProperty, value); }
+ }
+
+ public Color BackgroundColor
+ {
+ get { return (Color)GetValue(BackgroundColorProperty); }
+ set { SetValue(BackgroundColorProperty, value); }
+ }
+
+ public IList<Behavior> Behaviors
+ {
+ get { return (IList<Behavior>)GetValue(BehaviorsProperty); }
+ }
+
+ public Rectangle Bounds
+ {
+ get { return new Rectangle(X, Y, Width, Height); }
+ private set
+ {
+ if (value.X == X && value.Y == Y && value.Height == Height && value.Width == Width)
+ return;
+ BatchBegin();
+ X = value.X;
+ Y = value.Y;
+ SetSize(value.Width, value.Height);
+ BatchCommit();
+ }
+ }
+
+ public double Height
+ {
+ get { return _mockHeight == -1 ? (double)GetValue(HeightProperty) : _mockHeight; }
+ private set { SetValue(HeightPropertyKey, value); }
+ }
+
+ public double HeightRequest
+ {
+ get { return (double)GetValue(HeightRequestProperty); }
+ set { SetValue(HeightRequestProperty, value); }
+ }
+
+ public bool InputTransparent
+ {
+ get { return (bool)GetValue(InputTransparentProperty); }
+ set { SetValue(InputTransparentProperty, value); }
+ }
+
+ public bool IsEnabled
+ {
+ get { return (bool)GetValue(IsEnabledProperty); }
+ set { SetValue(IsEnabledProperty, value); }
+ }
+
+ public bool IsFocused
+ {
+ get { return (bool)GetValue(IsFocusedProperty); }
+ }
+
+ public bool IsVisible
+ {
+ get { return (bool)GetValue(IsVisibleProperty); }
+ set { SetValue(IsVisibleProperty, value); }
+ }
+
+ public double MinimumHeightRequest
+ {
+ get { return (double)GetValue(MinimumHeightRequestProperty); }
+ set { SetValue(MinimumHeightRequestProperty, value); }
+ }
+
+ public double MinimumWidthRequest
+ {
+ get { return (double)GetValue(MinimumWidthRequestProperty); }
+ set { SetValue(MinimumWidthRequestProperty, value); }
+ }
+
+ public INavigation Navigation
+ {
+ get { return (INavigation)GetValue(NavigationProperty); }
+ internal set { SetValue(NavigationPropertyKey, value); }
+ }
+
+ public double Opacity
+ {
+ get { return (double)GetValue(OpacityProperty); }
+ set { SetValue(OpacityProperty, value); }
+ }
+
+ public double Rotation
+ {
+ get { return (double)GetValue(RotationProperty); }
+ set { SetValue(RotationProperty, value); }
+ }
+
+ public double RotationX
+ {
+ get { return (double)GetValue(RotationXProperty); }
+ set { SetValue(RotationXProperty, value); }
+ }
+
+ public double RotationY
+ {
+ get { return (double)GetValue(RotationYProperty); }
+ set { SetValue(RotationYProperty, value); }
+ }
+
+ public double Scale
+ {
+ get { return (double)GetValue(ScaleProperty); }
+ set { SetValue(ScaleProperty, value); }
+ }
+
+ public Style Style
+ {
+ get { return (Style)GetValue(StyleProperty); }
+ set { SetValue(StyleProperty, value); }
+ }
+
+ public string StyleClass
+ {
+ get { return _mergedStyle.StyleClass; }
+ set { _mergedStyle.StyleClass = value; }
+ }
+
+ public double TranslationX
+ {
+ get { return (double)GetValue(TranslationXProperty); }
+ set { SetValue(TranslationXProperty, value); }
+ }
+
+ public double TranslationY
+ {
+ get { return (double)GetValue(TranslationYProperty); }
+ set { SetValue(TranslationYProperty, value); }
+ }
+
+ public IList<TriggerBase> Triggers
+ {
+ get { return (IList<TriggerBase>)GetValue(TriggersProperty); }
+ }
+
+ public double Width
+ {
+ get { return _mockWidth == -1 ? (double)GetValue(WidthProperty) : _mockWidth; }
+ private set { SetValue(WidthPropertyKey, value); }
+ }
+
+ public double WidthRequest
+ {
+ get { return (double)GetValue(WidthRequestProperty); }
+ set { SetValue(WidthRequestProperty, value); }
+ }
+
+ public double X
+ {
+ get { return _mockX == -1 ? (double)GetValue(XProperty) : _mockX; }
+ private set { SetValue(XPropertyKey, value); }
+ }
+
+ public double Y
+ {
+ get { return _mockY == -1 ? (double)GetValue(YProperty) : _mockY; }
+ private set { SetValue(YPropertyKey, value); }
+ }
+
+ internal bool Batched
+ {
+ get { return _batched > 0; }
+ }
+
+ internal LayoutConstraint ComputedConstraint
+ {
+ get { return _computedConstraint; }
+ set
+ {
+ if (_computedConstraint == value)
+ return;
+
+ LayoutConstraint oldConstraint = Constraint;
+ _computedConstraint = value;
+ LayoutConstraint newConstraint = Constraint;
+ if (oldConstraint != newConstraint)
+ OnConstraintChanged(oldConstraint, newConstraint);
+ }
+ }
+
+ internal LayoutConstraint Constraint
+ {
+ get { return ComputedConstraint | SelfConstraint; }
+ }
+
+ internal bool DisableLayout { get; set; }
+
+ internal bool IsInNativeLayout
+ {
+ get
+ {
+ if (_isInNativeLayout)
+ return true;
+
+ Element parent = RealParent;
+ while (parent != null)
+ {
+ var visualElement = parent as VisualElement;
+ if (visualElement != null && visualElement.IsInNativeLayout)
+ return true;
+ parent = parent.RealParent;
+ }
+
+ return false;
+ }
+ set { _isInNativeLayout = value; }
+ }
+
+ internal bool IsNativeStateConsistent
+ {
+ get { return _isNativeStateConsistent; }
+ set
+ {
+ if (_isNativeStateConsistent == value)
+ return;
+ _isNativeStateConsistent = value;
+ if (value && IsPlatformEnabled)
+ InvalidateMeasure(InvalidationTrigger.RendererReady);
+ }
+ }
+
+ internal bool IsPlatformEnabled
+ {
+ get { return _isPlatformEnabled; }
+ set
+ {
+ if (value == _isPlatformEnabled)
+ return;
+
+ _isPlatformEnabled = value;
+ if (value && IsNativeStateConsistent)
+ InvalidateMeasure(InvalidationTrigger.RendererReady);
+
+ OnIsPlatformEnabledChanged();
+ }
+ }
+
+ internal NavigationProxy NavigationProxy
+ {
+ get { return Navigation as NavigationProxy; }
+ }
+
+ internal LayoutConstraint SelfConstraint
+ {
+ get { return _selfConstraint; }
+ set
+ {
+ if (_selfConstraint == value)
+ return;
+
+ LayoutConstraint oldConstraint = Constraint;
+ _selfConstraint = value;
+ LayoutConstraint newConstraint = Constraint;
+ if (oldConstraint != newConstraint)
+ {
+ OnConstraintChanged(oldConstraint, newConstraint);
+ }
+ }
+ }
+
+ public void BatchBegin()
+ {
+ _batched++;
+ }
+
+ public void BatchCommit()
+ {
+ _batched = Math.Max(0, _batched - 1);
+ if (!Batched && BatchCommitted != null)
+ BatchCommitted(this, new EventArg<VisualElement>(this));
+ }
+
+ public ResourceDictionary Resources
+ {
+ get { return _resources; }
+ set
+ {
+ if (_resources == value)
+ return;
+ OnPropertyChanging();
+ if (_resources != null)
+ ((IResourceDictionary)_resources).ValuesChanged -= OnResourcesChanged;
+ _resources = value;
+ OnResourcesChanged(value);
+ if (_resources != null)
+ ((IResourceDictionary)_resources).ValuesChanged += OnResourcesChanged;
+ OnPropertyChanged();
+ }
+ }
+
+ void IVisualElementController.NativeSizeChanged()
+ {
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ public event EventHandler ChildrenReordered;
+
+ public bool Focus()
+ {
+ if (IsFocused)
+ return true;
+
+ if (FocusChangeRequested == null)
+ return false;
+
+ var arg = new FocusRequestArgs { Focus = true };
+ FocusChangeRequested(this, arg);
+ return arg.Result;
+ }
+
+ public event EventHandler<FocusEventArgs> Focused;
+
+ [Obsolete("Use Measure")]
+ public virtual SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest cachedResult;
+ var constraintSize = new Size(widthConstraint, heightConstraint);
+ if (_measureCache.TryGetValue(constraintSize, out cachedResult))
+ {
+ return cachedResult;
+ }
+
+ double widthRequest = WidthRequest;
+ double heightRequest = HeightRequest;
+ if (widthRequest >= 0)
+ widthConstraint = Math.Min(widthConstraint, widthRequest);
+ if (heightRequest >= 0)
+ heightConstraint = Math.Min(heightConstraint, heightRequest);
+
+ SizeRequest result = OnMeasure(widthConstraint, heightConstraint);
+ bool hasMinimum = result.Minimum != result.Request;
+ Size request = result.Request;
+ Size minimum = result.Minimum;
+
+ if (heightRequest != -1)
+ {
+ request.Height = heightRequest;
+ if (!hasMinimum)
+ minimum.Height = heightRequest;
+ }
+
+ if (widthRequest != -1)
+ {
+ request.Width = widthRequest;
+ if (!hasMinimum)
+ minimum.Width = widthRequest;
+ }
+
+ double minimumHeightRequest = MinimumHeightRequest;
+ double minimumWidthRequest = MinimumWidthRequest;
+
+ if (minimumHeightRequest != -1)
+ minimum.Height = minimumHeightRequest;
+ if (minimumWidthRequest != -1)
+ minimum.Width = minimumWidthRequest;
+
+ minimum.Height = Math.Min(request.Height, minimum.Height);
+ minimum.Width = Math.Min(request.Width, minimum.Width);
+
+ var r = new SizeRequest(request, minimum);
+
+ if (r.Request.Width > 0 && r.Request.Height > 0)
+ {
+ _measureCache[constraintSize] = r;
+ }
+
+ return r;
+ }
+
+ public void Layout(Rectangle bounds)
+ {
+ Bounds = bounds;
+ }
+
+ public SizeRequest Measure(double widthConstraint, double heightConstraint, MeasureFlags flags = MeasureFlags.None)
+ {
+ SizeRequest result = GetSizeRequest(widthConstraint, heightConstraint);
+
+ if ((flags & MeasureFlags.IncludeMargins) != 0)
+ {
+ Thickness margin = default(Thickness);
+ var view = this as View;
+ if (view != null)
+ margin = view.Margin;
+
+ if (!margin.IsDefault)
+ {
+ result.Minimum = new Size(result.Minimum.Width + margin.HorizontalThickness, result.Minimum.Height + margin.VerticalThickness);
+ result.Request = new Size(result.Request.Width + margin.HorizontalThickness, result.Request.Height + margin.VerticalThickness);
+ }
+ }
+
+ return result;
+ }
+
+ public event EventHandler MeasureInvalidated;
+
+ public event EventHandler SizeChanged;
+
+ public void Unfocus()
+ {
+ if (!IsFocused)
+ return;
+
+ EventHandler<FocusRequestArgs> unfocus = FocusChangeRequested;
+ if (unfocus != null)
+ {
+ unfocus(this, new FocusRequestArgs());
+ }
+ }
+
+ public event EventHandler<FocusEventArgs> Unfocused;
+
+ protected virtual void InvalidateMeasure()
+ {
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ protected override void OnChildAdded(Element child)
+ {
+ base.OnChildAdded(child);
+ var view = child as View;
+ if (view != null)
+ ComputeConstraintForView(view);
+ }
+
+ protected override void OnChildRemoved(Element child)
+ {
+ base.OnChildRemoved(child);
+ var view = child as View;
+ if (view != null)
+ view.ComputedConstraint = LayoutConstraint.None;
+ }
+
+ protected void OnChildrenReordered()
+ {
+ if (ChildrenReordered != null)
+ ChildrenReordered(this, EventArgs.Empty);
+ }
+
+ protected virtual SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+ {
+ return OnSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ protected override void OnParentSet()
+ {
+ base.OnParentSet();
+
+ if (ParentView != null)
+ {
+ NavigationProxy.Inner = ParentView.NavigationProxy;
+ }
+ else
+ {
+ NavigationProxy.Inner = null;
+ }
+ }
+
+ protected virtual void OnSizeAllocated(double width, double height)
+ {
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected virtual SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ if (Platform == null || !IsPlatformEnabled)
+ {
+ return new SizeRequest(new Size(-1, -1));
+ }
+ return Platform.GetNativeSize(this, widthConstraint, heightConstraint);
+ }
+
+ protected void SizeAllocated(double width, double height)
+ {
+ OnSizeAllocated(width, height);
+ }
+
+ internal event EventHandler<EventArg<VisualElement>> BatchCommitted;
+
+ internal void ComputeConstrainsForChildren()
+ {
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = LogicalChildren[i] as View;
+ if (child != null)
+ ComputeConstraintForView(child);
+ }
+ }
+
+ internal virtual void ComputeConstraintForView(View view)
+ {
+ view.ComputedConstraint = LayoutConstraint.None;
+ }
+
+ internal event EventHandler<FocusRequestArgs> FocusChangeRequested;
+
+ internal virtual void InvalidateMeasure(InvalidationTrigger trigger)
+ {
+ _measureCache.Clear();
+ MeasureInvalidated?.Invoke(this, new InvalidationEventArgs(trigger));
+ }
+
+ internal void MockBounds(Rectangle bounds)
+ {
+ _mockX = bounds.X;
+ _mockY = bounds.Y;
+ _mockWidth = bounds.Width;
+ _mockHeight = bounds.Height;
+ }
+
+ internal virtual void OnConstraintChanged(LayoutConstraint oldConstraint, LayoutConstraint newConstraint)
+ {
+ ComputeConstrainsForChildren();
+ }
+
+ internal virtual void OnIsPlatformEnabledChanged()
+ {
+ }
+
+ internal virtual void OnIsVisibleChanged(bool oldValue, bool newValue)
+ {
+ InvalidateMeasure(InvalidationTrigger.Undefined);
+ }
+
+ internal override void OnParentResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
+ {
+ if (values == null)
+ return;
+
+ if (Resources == null || Resources.Count == 0)
+ {
+ base.OnParentResourcesChanged(values);
+ return;
+ }
+
+ var innerKeys = new HashSet<string>();
+ var changedResources = new List<KeyValuePair<string, object>>();
+ foreach (KeyValuePair<string, object> c in Resources)
+ innerKeys.Add(c.Key);
+ foreach (KeyValuePair<string, object> value in values)
+ {
+ if (innerKeys.Add(value.Key))
+ changedResources.Add(value);
+ else if (value.Key.StartsWith(Style.StyleClassPrefix, StringComparison.Ordinal))
+ {
+ var mergedClassStyles = new List<Style>(Resources[value.Key] as List<Style>);
+ mergedClassStyles.AddRange(value.Value as List<Style>);
+ changedResources.Add(new KeyValuePair<string, object>(value.Key, mergedClassStyles));
+ }
+ }
+ if (changedResources.Count != 0)
+ OnResourcesChanged(changedResources);
+ }
+
+ internal void UnmockBounds()
+ {
+ _mockX = _mockY = _mockWidth = _mockHeight = -1;
+ }
+
+ void OnFocused()
+ {
+ EventHandler<FocusEventArgs> focus = Focused;
+ if (focus != null)
+ focus(this, new FocusEventArgs(this, true));
+ }
+
+ static void OnIsFocusedPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ var element = bindable as VisualElement;
+
+ var isFocused = (bool)newvalue;
+ if (isFocused)
+ {
+ element.OnFocused();
+ }
+ else
+ {
+ element.OnUnfocus();
+ }
+ }
+
+ static void OnRequestChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ var constraint = LayoutConstraint.None;
+ var element = (VisualElement)bindable;
+ if (element.WidthRequest >= 0 && element.MinimumWidthRequest >= 0)
+ {
+ constraint |= LayoutConstraint.HorizontallyFixed;
+ }
+ if (element.HeightRequest >= 0 && element.MinimumHeightRequest >= 0)
+ {
+ constraint |= LayoutConstraint.VerticallyFixed;
+ }
+
+ element.SelfConstraint = constraint;
+ ((VisualElement)bindable).InvalidateMeasure(InvalidationTrigger.SizeRequestChanged);
+ }
+
+ void OnUnfocus()
+ {
+ EventHandler<FocusEventArgs> unFocus = Unfocused;
+ if (unFocus != null)
+ unFocus(this, new FocusEventArgs(this, false));
+ }
+
+ void SetSize(double width, double height)
+ {
+ if (Width == width && Height == height)
+ return;
+
+ Width = width;
+ Height = height;
+
+ SizeAllocated(width, height);
+ if (SizeChanged != null)
+ SizeChanged(this, EventArgs.Empty);
+ }
+
+ internal class FocusRequestArgs : EventArgs
+ {
+ public bool Focus { get; set; }
+
+ public bool Result { get; set; }
+ }
+ }
+} \ No newline at end of file