Browse Source

Fix: RangeBase should not write coerced values back when DataContext is changing (#11918)

* Add failing test for RangeBase overriding Value on DataContext changed

* Add bool flag to skip coercing min, max and value while DataContext is 

changing
pull/13818/head
Tim 2 years ago
committed by GitHub
parent
commit
d7c82a1a6f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      src/Avalonia.Controls/Primitives/RangeBase.cs
  2. 34
      tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs

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

@ -10,6 +10,8 @@ namespace Avalonia.Controls.Primitives
/// </summary> /// </summary>
public abstract class RangeBase : TemplatedControl public abstract class RangeBase : TemplatedControl
{ {
private bool _isDataContextChanging;
/// <summary> /// <summary>
/// Defines the <see cref="Minimum"/> property. /// Defines the <see cref="Minimum"/> property.
/// </summary> /// </summary>
@ -74,7 +76,7 @@ namespace Avalonia.Controls.Primitives
private void OnMinimumChanged() private void OnMinimumChanged()
{ {
if (IsInitialized) if (IsInitialized && !_isDataContextChanging)
{ {
CoerceValue(MaximumProperty); CoerceValue(MaximumProperty);
CoerceValue(ValueProperty); CoerceValue(ValueProperty);
@ -99,8 +101,9 @@ namespace Avalonia.Controls.Primitives
private void OnMaximumChanged() private void OnMaximumChanged()
{ {
if (IsInitialized) if (IsInitialized && !_isDataContextChanging)
{ {
CoerceValue(MinimumProperty);
CoerceValue(ValueProperty); CoerceValue(ValueProperty);
} }
} }
@ -170,6 +173,20 @@ namespace Avalonia.Controls.Primitives
RaiseEvent(valueChangedEventArgs); RaiseEvent(valueChangedEventArgs);
} }
} }
/// <inheritdoc />
protected override void OnDataContextBeginUpdate()
{
_isDataContextChanging = true;
base.OnDataContextBeginUpdate();
}
/// <inheritdoc />
protected override void OnDataContextEndUpdate()
{
base.OnDataContextEndUpdate();
_isDataContextChanging = false;
}
/// <summary> /// <summary>
/// Checks if the double value is not infinity nor NaN. /// Checks if the double value is not infinity nor NaN.

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

@ -1,5 +1,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Security.Cryptography.X509Certificates;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
@ -27,6 +28,32 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Equal(100, target.Maximum); Assert.Equal(100, target.Maximum);
} }
[Fact]
public void ChangingDataContextShouldNotChangeOldDataContext()
{
var viewModel = new RangeTestViewModel()
{
Minimum = -5000,
Maximum = 5000,
Value = 4000
};
var target = new TestRange
{
[!RangeBase.MinimumProperty] = new Binding(nameof(viewModel.Minimum)),
[!RangeBase.MaximumProperty] = new Binding(nameof(viewModel.Maximum)),
[!RangeBase.ValueProperty] = new Binding(nameof(viewModel.Value)),
};
var root = new TestRoot(target);
target.DataContext = viewModel;
target.DataContext = null;
Assert.Equal(4000, viewModel.Value);
Assert.Equal(-5000, viewModel.Minimum);
Assert.Equal(5000, viewModel.Maximum);
}
[Fact] [Fact]
public void Value_Should_Be_Coerced_To_Range() public void Value_Should_Be_Coerced_To_Range()
{ {
@ -217,5 +244,12 @@ namespace Avalonia.Controls.UnitTests.Primitives
} }
} }
} }
private class RangeTestViewModel
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public double Value { get; set; }
}
} }
} }

Loading…
Cancel
Save