Skip to content

Commit

Permalink
Fix: RangeBase should not write coerced values back when DataContext …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
timunie authored and maxkatz6 committed Dec 5, 2023
1 parent 3c2ac1c commit 9848d55
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/Avalonia.Controls/Primitives/RangeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace Avalonia.Controls.Primitives
/// </summary>
public abstract class RangeBase : TemplatedControl
{
private bool _isDataContextChanging;

/// <summary>
/// Defines the <see cref="Minimum"/> property.
/// </summary>
Expand Down Expand Up @@ -74,7 +76,7 @@ private static double CoerceMinimum(AvaloniaObject sender, double value)

private void OnMinimumChanged()
{
if (IsInitialized)
if (IsInitialized && !_isDataContextChanging)
{
CoerceValue(MaximumProperty);
CoerceValue(ValueProperty);
Expand All @@ -99,8 +101,9 @@ private static double CoerceMaximum(AvaloniaObject sender, double value)

private void OnMaximumChanged()
{
if (IsInitialized)
if (IsInitialized && !_isDataContextChanging)
{
CoerceValue(MinimumProperty);
CoerceValue(ValueProperty);
}
}
Expand Down Expand Up @@ -170,6 +173,20 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
RaiseEvent(valueChangedEventArgs);
}
}

/// <inheritdoc />
protected override void OnDataContextBeginUpdate()
{
_isDataContextChanging = true;
base.OnDataContextBeginUpdate();
}

/// <inheritdoc />
protected override void OnDataContextEndUpdate()
{
base.OnDataContextEndUpdate();
_isDataContextChanging = false;
}

/// <summary>
/// Checks if the double value is not infinity nor NaN.
Expand Down
34 changes: 34 additions & 0 deletions tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Security.Cryptography.X509Certificates;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
Expand Down Expand Up @@ -27,6 +28,32 @@ public void Maximum_Should_Be_Coerced_To_Minimum()
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]
public void Value_Should_Be_Coerced_To_Range()
{
Expand Down Expand Up @@ -217,5 +244,12 @@ public double Value
}
}
}

private class RangeTestViewModel
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public double Value { get; set; }
}
}
}

0 comments on commit 9848d55

Please sign in to comment.