Browse Source

Merge pull request #2683 from AvaloniaUI/fixes/2372-slider-coercion

Don't coerce RangeBase values until initialized.
no-llvmpipe
Nikita Tsukanov 7 years ago
committed by GitHub
parent
commit
a6f8e523bf
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 65
      src/Avalonia.Controls/Primitives/RangeBase.cs
  2. 10
      src/Avalonia.Styling/StyledElement.cs
  3. 39
      tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs
  4. 19
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

65
src/Avalonia.Controls/Primitives/RangeBase.cs

@ -75,10 +75,18 @@ namespace Avalonia.Controls.Primitives
set set
{ {
value = ValidateMinimum(value); ValidateDouble(value, "Minimum");
SetAndRaise(MinimumProperty, ref _minimum, value);
Maximum = ValidateMaximum(Maximum); if (IsInitialized)
Value = ValidateValue(Value); {
SetAndRaise(MinimumProperty, ref _minimum, value);
Maximum = ValidateMaximum(Maximum);
Value = ValidateValue(Value);
}
else
{
SetAndRaise(MinimumProperty, ref _minimum, value);
}
} }
} }
@ -94,9 +102,18 @@ namespace Avalonia.Controls.Primitives
set set
{ {
value = ValidateMaximum(value); ValidateDouble(value, "Maximum");
SetAndRaise(MaximumProperty, ref _maximum, value);
Value = ValidateValue(Value); if (IsInitialized)
{
value = ValidateMaximum(value);
SetAndRaise(MaximumProperty, ref _maximum, value);
Value = ValidateValue(Value);
}
else
{
SetAndRaise(MaximumProperty, ref _maximum, value);
}
} }
} }
@ -112,8 +129,17 @@ namespace Avalonia.Controls.Primitives
set set
{ {
value = ValidateValue(value); ValidateDouble(value, "Value");
SetAndRaise(ValueProperty, ref _value, value);
if (IsInitialized)
{
value = ValidateValue(value);
SetAndRaise(ValueProperty, ref _value, value);
}
else
{
SetAndRaise(ValueProperty, ref _value, value);
}
} }
} }
@ -129,6 +155,14 @@ namespace Avalonia.Controls.Primitives
set => SetValue(LargeChangeProperty, value); set => SetValue(LargeChangeProperty, value);
} }
protected override void OnInitialized()
{
base.OnInitialized();
Maximum = ValidateMaximum(Maximum);
Value = ValidateValue(Value);
}
/// <summary> /// <summary>
/// Throws an exception if the double value is NaN or Inf. /// Throws an exception if the double value is NaN or Inf.
/// </summary> /// </summary>
@ -142,17 +176,6 @@ namespace Avalonia.Controls.Primitives
} }
} }
/// <summary>
/// Validates the <see cref="Minimum"/> property.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The coerced value.</returns>
private double ValidateMinimum(double value)
{
ValidateDouble(value, "Minimum");
return value;
}
/// <summary> /// <summary>
/// Validates/coerces the <see cref="Maximum"/> property. /// Validates/coerces the <see cref="Maximum"/> property.
/// </summary> /// </summary>
@ -160,7 +183,6 @@ namespace Avalonia.Controls.Primitives
/// <returns>The coerced value.</returns> /// <returns>The coerced value.</returns>
private double ValidateMaximum(double value) private double ValidateMaximum(double value)
{ {
ValidateDouble(value, "Maximum");
return Math.Max(value, Minimum); return Math.Max(value, Minimum);
} }
@ -171,7 +193,6 @@ namespace Avalonia.Controls.Primitives
/// <returns>The coerced value.</returns> /// <returns>The coerced value.</returns>
private double ValidateValue(double value) private double ValidateValue(double value)
{ {
ValidateDouble(value, "Value");
return MathUtilities.Clamp(value, Minimum, Maximum); return MathUtilities.Clamp(value, Minimum, Maximum);
} }
} }

10
src/Avalonia.Styling/StyledElement.cs

@ -392,6 +392,7 @@ namespace Avalonia
if (_initCount == 0 && !IsInitialized) if (_initCount == 0 && !IsInitialized)
{ {
IsInitialized = true; IsInitialized = true;
OnInitialized();
Initialized?.Invoke(this, EventArgs.Empty); Initialized?.Invoke(this, EventArgs.Empty);
} }
} }
@ -608,7 +609,14 @@ namespace Avalonia
protected virtual void OnDataContextEndUpdate() protected virtual void OnDataContextEndUpdate()
{ {
} }
/// <summary>
/// Called when the control finishes initialization.
/// </summary>
protected virtual void OnInitialized()
{
}
private static void DataContextNotifying(IAvaloniaObject o, bool updateStarted) private static void DataContextNotifying(IAvaloniaObject o, bool updateStarted)
{ {
if (o is StyledElement element) if (o is StyledElement element)

39
tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs

@ -8,6 +8,7 @@ using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Markup.Data; using Avalonia.Markup.Data;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.UnitTests;
using Xunit; using Xunit;
namespace Avalonia.Controls.UnitTests.Primitives namespace Avalonia.Controls.UnitTests.Primitives
@ -22,6 +23,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Minimum = 100, Minimum = 100,
Maximum = 50, Maximum = 50,
}; };
var root = new TestRoot(target);
Assert.Equal(100, target.Minimum); Assert.Equal(100, target.Minimum);
Assert.Equal(100, target.Maximum); Assert.Equal(100, target.Maximum);
@ -36,6 +38,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Maximum = 50, Maximum = 50,
Value = 100, Value = 100,
}; };
var root = new TestRoot(target);
Assert.Equal(0, target.Minimum); Assert.Equal(0, target.Minimum);
Assert.Equal(50, target.Maximum); Assert.Equal(50, target.Maximum);
@ -51,6 +54,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Maximum = 100, Maximum = 100,
Value = 50, Value = 50,
}; };
var root = new TestRoot(target);
target.Minimum = 200; target.Minimum = 200;
@ -68,6 +72,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Maximum = 100, Maximum = 100,
Value = 100, Value = 100,
}; };
var root = new TestRoot(target);
target.Maximum = 50; target.Maximum = 50;
@ -160,6 +165,38 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Equal(expected, track.Value); Assert.Equal(expected, track.Value);
} }
[Fact]
public void Coercion_Should_Not_Be_Done_During_Initialization()
{
var target = new TestRange();
target.BeginInit();
var root = new TestRoot(target);
target.Minimum = 1;
Assert.Equal(0, target.Value);
target.Value = 50;
target.EndInit();
Assert.Equal(50, target.Value);
}
[Fact]
public void Coercion_Should_Be_Done_After_Initialization()
{
var target = new TestRange();
target.BeginInit();
var root = new TestRoot(target);
target.Minimum = 1;
target.EndInit();
Assert.Equal(1, target.Value);
}
private class TestRange : RangeBase private class TestRange : RangeBase
{ {
} }
@ -199,4 +236,4 @@ namespace Avalonia.Controls.UnitTests.Primitives
} }
} }
} }
} }

19
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -907,6 +907,25 @@ do we need it?")]
} }
} }
[Fact]
public void Slider_Properties_Can_Be_Set_In_Any_Order()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'>
<Slider Width='400' Value='500' Minimum='0' Maximum='1000'/>
</Window>";
var window = AvaloniaXamlLoader.Parse<Window>(xaml);
var slider = (Slider)window.Content;
Assert.Equal(0, slider.Minimum);
Assert.Equal(1000, slider.Maximum);
Assert.Equal(500, slider.Value);
}
}
private class SelectedItemsViewModel : INotifyPropertyChanged private class SelectedItemsViewModel : INotifyPropertyChanged
{ {
public string[] Items { get; set; } public string[] Items { get; set; }

Loading…
Cancel
Save