diff --git a/src/Avalonia.Base/Layout/Layoutable.cs b/src/Avalonia.Base/Layout/Layoutable.cs
index b237c10e63..73c9e1ba0f 100644
--- a/src/Avalonia.Base/Layout/Layoutable.cs
+++ b/src/Avalonia.Base/Layout/Layoutable.cs
@@ -74,37 +74,37 @@ namespace Avalonia.Layout
/// Defines the property.
///
public static readonly StyledProperty WidthProperty =
- AvaloniaProperty.Register(nameof(Width), double.NaN);
+ AvaloniaProperty.Register(nameof(Width), double.NaN, validate: ValidateDimension);
///
/// Defines the property.
///
public static readonly StyledProperty HeightProperty =
- AvaloniaProperty.Register(nameof(Height), double.NaN);
+ AvaloniaProperty.Register(nameof(Height), double.NaN, validate: ValidateDimension);
///
/// Defines the property.
///
public static readonly StyledProperty MinWidthProperty =
- AvaloniaProperty.Register(nameof(MinWidth));
+ AvaloniaProperty.Register(nameof(MinWidth), validate: ValidateMinimumDimension);
///
/// Defines the property.
///
public static readonly StyledProperty MaxWidthProperty =
- AvaloniaProperty.Register(nameof(MaxWidth), double.PositiveInfinity);
+ AvaloniaProperty.Register(nameof(MaxWidth), double.PositiveInfinity, validate: ValidateMaximumDimension);
///
/// Defines the property.
///
public static readonly StyledProperty MinHeightProperty =
- AvaloniaProperty.Register(nameof(MinHeight));
+ AvaloniaProperty.Register(nameof(MinHeight), validate: ValidateMinimumDimension);
///
/// Defines the property.
///
public static readonly StyledProperty MaxHeightProperty =
- AvaloniaProperty.Register(nameof(MaxHeight), double.PositiveInfinity);
+ AvaloniaProperty.Register(nameof(MaxHeight), double.PositiveInfinity, validate: ValidateMaximumDimension);
///
/// Defines the property.
@@ -153,6 +153,10 @@ namespace Avalonia.Layout
VerticalAlignmentProperty);
}
+ private static bool ValidateDimension(double value) => double.IsNaN(value) || ValidateMinimumDimension(value);
+ private static bool ValidateMinimumDimension(double value) => !double.IsPositiveInfinity(value) && ValidateMaximumDimension(value);
+ private static bool ValidateMaximumDimension(double value) => value >= 0;
+
///
/// Occurs when the element's effective viewport changes.
///
diff --git a/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs b/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs
index c4b0795022..ab1c036b72 100644
--- a/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.UnitTests;
@@ -387,6 +388,29 @@ namespace Avalonia.Base.UnitTests.Layout
Assert.Equal(default, child.DesiredSize);
}
+ [Fact]
+ public void Size_Properties_Reject_Invalid_Values()
+ {
+ var target = new Layoutable();
+
+ Assert.Multiple(() =>
+ {
+ SetShouldThrow([Layoutable.WidthProperty, Layoutable.HeightProperty], double.PositiveInfinity);
+ SetShouldThrow([Layoutable.WidthProperty, Layoutable.HeightProperty], -10);
+
+ SetShouldThrow([Layoutable.MinWidthProperty, Layoutable.MinHeightProperty], double.PositiveInfinity);
+ SetShouldThrow([Layoutable.MinWidthProperty, Layoutable.MinHeightProperty], -10);
+
+ SetShouldThrow([Layoutable.MaxWidthProperty, Layoutable.MaxHeightProperty], -10);
+
+ void SetShouldThrow(IEnumerable> properies, double value)
+ {
+ foreach (var prop in properies)
+ Assert.Throws(() => target.SetValue(prop, value));
+ }
+ });
+ }
+
private class TestLayoutable : Layoutable
{
public Size ArrangeSize { get; private set; }