From dee1edf7f12d98001f8a40119c88bdce44dc98e3 Mon Sep 17 00:00:00 2001 From: Fidarit Mullayanov Date: Sun, 19 Apr 2026 17:03:30 +0500 Subject: [PATCH 1/3] breaking: drop old tf support (net48, netstandard) --- Directory.Build.props | 10 +-- .../ViewModels/DynamicColumnsViewModel.cs | 4 +- .../Avalonia.Controls.TreeDataGrid.csproj | 16 +---- .../Models/TreeDataGrid/AnonymousRow.cs | 4 -- .../Models/TreeDataGrid/HierarchicalRow.cs | 4 -- .../Models/TreeDataGrid/IRow`1.cs | 2 - .../Models/TreeDataGrid/IRows.cs | 2 +- .../Primitives/TreeDataGridPresenterBase.cs | 2 +- .../TreeDataGridCellSelectionModel.cs | 5 -- .../StandardExtensions/BitOperations.cs | 67 ------------------- .../StandardExtensions/Double.cs | 13 ---- .../TreeDataGrid.cs | 2 - .../Utils/StableSort.cs | 4 -- ...nia.Controls.TreeDataGrid.Benchmark.csproj | 10 +-- .../Benchmarks.cs | 2 +- .../Program.cs | 4 -- .../FlatTreeDataGridSourceTests.cs | 4 +- .../TreeDataGridRowsPresenterTests.cs | 1 + .../TreeSelectionModelBaseTests_Multiple.cs | 4 +- 19 files changed, 16 insertions(+), 144 deletions(-) delete mode 100644 src/Avalonia.Controls.TreeDataGrid/StandardExtensions/BitOperations.cs delete mode 100644 src/Avalonia.Controls.TreeDataGrid/StandardExtensions/Double.cs diff --git a/Directory.Build.props b/Directory.Build.props index 347d4395..38cd198f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,17 +8,9 @@ false false - - - - true nullable - - - - - $(NoWarn);8604;8602 + $(NoWarn);NU1903 diff --git a/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs b/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs index db2d6e04..b61e9e34 100644 --- a/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs +++ b/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs @@ -50,8 +50,8 @@ private void OnColumnCountChanged(int newValue) { TextSearchValueSelector = value => value.Value, IsReadOnlyGetter = value => value.ReadOnly, - CompareAscending = (a, b) => Comparer.Default.Compare(a.Value, b.Value), - CompareDescending = (b, a) => Comparer.Default.Compare(a.Value, b.Value), + CompareAscending = (a, b) => Comparer.Default.Compare(a?.Value, b?.Value), + CompareDescending = (b, a) => Comparer.Default.Compare(a?.Value, b?.Value), })); } } diff --git a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj index 07fa28b3..0f966b34 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj +++ b/src/Avalonia.Controls.TreeDataGrid/Avalonia.Controls.TreeDataGrid.csproj @@ -1,6 +1,6 @@  - netstandard2.0;net8.0;net10.0;net48 + net8.0;net10.0 True Avalonia.Controls readme.md @@ -19,23 +19,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs index e218f5f5..6829da91 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousRow.cs @@ -17,10 +17,6 @@ internal class AnonymousRow : IRow, IModelIndexableRow private int _modelIndex; [AllowNull] private TModel _model; -#if !NET5_0_OR_GREATER - object? IRow.Model => _model; -#endif - public object? Header => _modelIndex; public TModel Model => _model; public int ModelIndex => _modelIndex; diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRow.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRow.cs index ddb3f5b2..5e136642 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRow.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRow.cs @@ -22,10 +22,6 @@ public class HierarchicalRow : NotifyingBase, private bool _isExpanded; private bool? _showExpander; -#if !NET5_0_OR_GREATER - object? IRow.Model => Model; -#endif - public HierarchicalRow( IExpanderRowController controller, IExpanderColumn expanderColumn, diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRow`1.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRow`1.cs index e4f57b7a..d48b2c0e 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRow`1.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRow`1.cs @@ -11,12 +11,10 @@ public interface IRow : IRow /// new TModel Model { get; } -#if !!NET5_0_OR_GREATER /// /// Gets the untyped row model. /// object? IRow.Model => Model; -#endif /// /// Updates the model index due to a change in the data source. diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRows.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRows.cs index 30d7670b..c12f66e7 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRows.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/IRows.cs @@ -25,7 +25,7 @@ public interface IRows : IReadOnlyList, INotifyCollectionChanged (int index, double y) GetRowAt(double y); /// - /// Given a model index, returns an index into . + /// Given a model index, returns an index into . /// /// The model index. /// The row index, or -1 if the model index is not displayed. diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs index e5d03e37..54573228 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs @@ -215,7 +215,7 @@ protected virtual Size MeasureElement(int index, Control element, Size available /// - The final pass is made once the "natural" sizes of the elements are known and any /// layout logic has been run. This pass is needed because controls should not be /// arranged with a size less than that passed as the constraint during the measure - /// pass. This pass is only run if returns + /// pass. This pass is only run if returns /// true. /// protected virtual Size GetInitialConstraint( diff --git a/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs b/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs index 6f87d485..cbe1de64 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs @@ -128,13 +128,8 @@ sender.Rows is null || var anchor = shift ? _rangeAnchor : GetAnchor(); -#if !NET5_0_OR_GREATER - var columnIndex = Math.Min(Math.Max(anchor.x + x, 0), sender.Columns.Count - 1); - var rowIndex = Math.Min(Math.Max(anchor.y + y, 0), sender.Rows.Count - 1); -#else var columnIndex = Math.Clamp(anchor.x + x, 0, sender.Columns.Count - 1); var rowIndex = Math.Clamp(anchor.y + y, 0, sender.Rows.Count - 1); -#endif if (!shift) Select(columnIndex, rowIndex); diff --git a/src/Avalonia.Controls.TreeDataGrid/StandardExtensions/BitOperations.cs b/src/Avalonia.Controls.TreeDataGrid/StandardExtensions/BitOperations.cs deleted file mode 100644 index cb38ed25..00000000 --- a/src/Avalonia.Controls.TreeDataGrid/StandardExtensions/BitOperations.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -// Some routines inspired by the Stanford Bit Twiddling Hacks by Sean Eron Anderson: -// http://graphics.stanford.edu/~seander/bithacks.html - -namespace System.Numerics -{ - /// - /// Utility methods for intrinsic bit-twiddling operations. - /// The methods use hardware intrinsics when available on the underlying platform, - /// otherwise they use optimized software fallbacks. - /// - internal static class BitOperations - { - // C# no-alloc optimization that directly wraps the data section of the dll (similar to string constants) - // https://github.com/dotnet/roslyn/pull/24621 - - private static ReadOnlySpan Log2DeBruijn => // 32 - [ - 00, 09, 01, 10, 13, 21, 02, 29, - 11, 14, 16, 18, 22, 25, 03, 30, - 08, 12, 20, 28, 15, 17, 24, 07, - 19, 27, 23, 06, 26, 05, 04, 31 - ]; - - /// - /// Returns the integer (floor) log of the specified value, base 2. - /// Note that by convention, input value 0 returns 0 since log(0) is undefined. - /// - /// The value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Log2(uint value) - { - // The 0->0 contract is fulfilled by setting the LSB to 1. - // Log(1) is 0, and setting the LSB for values > 1 does not change the log2 result. - value |= 1; - - // Fallback contract is 0->0 - return Log2SoftwareFallback(value); - } - - /// - /// Returns the integer (floor) log of the specified value, base 2. - /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. - /// Does not directly use any hardware intrinsics, nor does it incur branching. - /// - /// The value. - private static int Log2SoftwareFallback(uint value) - { - // No AggressiveInlining due to large method size - // Has conventional contract 0->0 (Log(0) is undefined) - - // Fill trailing zeros with ones, eg 00010010 becomes 00011111 - value |= value >> 01; - value |= value >> 02; - value |= value >> 04; - value |= value >> 08; - value |= value >> 16; - - // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u - return Log2DeBruijn[(int)((value * 0x07C4ACDDu) >> 27)]; - } - } -} diff --git a/src/Avalonia.Controls.TreeDataGrid/StandardExtensions/Double.cs b/src/Avalonia.Controls.TreeDataGrid/StandardExtensions/Double.cs deleted file mode 100644 index a465956c..00000000 --- a/src/Avalonia.Controls.TreeDataGrid/StandardExtensions/Double.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Avalonia; - - -internal static class Double -{ - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsFinite(double value) - { - return !double.IsNaN(value) && !double.IsInfinity(value); - } -} diff --git a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs index db5f3570..1fa94177 100644 --- a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs +++ b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs @@ -675,9 +675,7 @@ private void AutoScroll(bool direction) _autoScrollTimer.Start(); } -#if NET5_0_OR_GREATER [MemberNotNullWhen(true, nameof(_source))] -#endif private bool CalculateAutoDragDrop( TreeDataGridRow? targetRow, DragEventArgs e, diff --git a/src/Avalonia.Controls.TreeDataGrid/Utils/StableSort.cs b/src/Avalonia.Controls.TreeDataGrid/Utils/StableSort.cs index 9597e4fb..c34aee36 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Utils/StableSort.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Utils/StableSort.cs @@ -19,12 +19,8 @@ public static List SortedMap(IReadOnlyList elements, Comparison map.Add(i); } -#if !NET5_0_OR_GREATER - map.Sort(compare); -#else var span = CollectionsMarshal.AsSpan(map); SortHelper.Sort(span, compare); -#endif return map; } diff --git a/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Avalonia.Controls.TreeDataGrid.Benchmark.csproj b/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Avalonia.Controls.TreeDataGrid.Benchmark.csproj index 61b5d8ac..6798ad7e 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Avalonia.Controls.TreeDataGrid.Benchmark.csproj +++ b/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Avalonia.Controls.TreeDataGrid.Benchmark.csproj @@ -1,7 +1,7 @@  - net48;net10.0 + net10.0 Exe Avalonia.Controls.TreeDataGridBenchmark @@ -16,13 +16,7 @@ - - - TargetFramework=net48 - - - - + diff --git a/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Benchmarks.cs b/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Benchmarks.cs index 2e0e6590..c0bb1a29 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Benchmarks.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Benchmarks.cs @@ -16,7 +16,7 @@ public class Benchmarks private const int RowCount = 500; private const int ColumnCount = 40; - private TreeDataGrid? _target; + private TreeDataGrid _target = default!; [GlobalSetup] public void Setup() diff --git a/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Program.cs b/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Program.cs index c5f7c5b7..9607faed 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Program.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Benchmark/Program.cs @@ -1,7 +1,5 @@ using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Environments; -using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Running; namespace Avalonia.Controls.TreeDataGridBenchmark; @@ -11,8 +9,6 @@ internal class Program private static void Main(string[] args) { var _ = BenchmarkRunner.Run(typeof(Program).Assembly, DefaultConfig.Instance - .AddJob(Job.Default.WithRuntime(ClrRuntime.Net48)) - .AddJob(Job.Default.WithRuntime(CoreRuntime.Core10_0)) .AddDiagnoser(MemoryDiagnoser.Default)); } } diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/FlatTreeDataGridSourceTests.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/FlatTreeDataGridSourceTests.cs index 2f70c5d1..48632b24 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/FlatTreeDataGridSourceTests.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/FlatTreeDataGridSourceTests.cs @@ -199,6 +199,7 @@ public void Supports_Adding_Row() { Assert.Equal(NotifyCollectionChangedAction.Add, e.Action); Assert.Equal(0, e.NewStartingIndex); + Assert.NotNull(e.NewItems); Assert.Single(e.NewItems); Assert.Equal(10, ((IModelIndexableRow)e.NewItems[0]!).ModelIndex); ++raised; @@ -225,7 +226,8 @@ public void Supports_Removing_Row() { Assert.Equal(NotifyCollectionChangedAction.Remove, e.Action); Assert.Equal(4, e.OldStartingIndex); - Assert.Single(e.OldItems!); + Assert.NotNull(e.OldItems); + Assert.Single(e.OldItems); Assert.Equal(5, ((IModelIndexableRow)e.OldItems[0]!).ModelIndex); ++raised; }; diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/Primitives/TreeDataGridRowsPresenterTests.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/Primitives/TreeDataGridRowsPresenterTests.cs index f492a8c0..590f379a 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/Primitives/TreeDataGridRowsPresenterTests.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/Primitives/TreeDataGridRowsPresenterTests.cs @@ -226,6 +226,7 @@ public void Should_Remove_Children_On_Empty_Collection_Assignment_To_Items() Assert.Equal(100, items.Count); items.RemoveRange(1, 99); Layout(target); + Assert.NotNull(target.Items); Assert.Single(target.Items); Assert.Single(target.GetVisualChildren()); diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeSelectionModelBaseTests_Multiple.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeSelectionModelBaseTests_Multiple.cs index c0ddda08..77c30011 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeSelectionModelBaseTests_Multiple.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeSelectionModelBaseTests_Multiple.cs @@ -1502,7 +1502,9 @@ public void Clearing_Node_Selection_Unsubscribes_From_CollectionChanged() target.Select(new IndexPath(1, 1)); var debug = (AvaloniaListDebug)data[1].Children!; - Assert.Single(debug.GetCollectionChangedSubscribers()); + var subs = debug.GetCollectionChangedSubscribers(); + Assert.NotNull(subs); + Assert.Single(subs); target.Deselect(new IndexPath(1, 1)); From b6fb0fa14446710ac674c19d8fa5e79f7ce7f3f3 Mon Sep 17 00:00:00 2001 From: Fidarit Mullayanov Date: Sun, 19 Apr 2026 19:26:38 +0500 Subject: [PATCH 2/3] drag-and-drop rework --- Directory.Build.props | 4 +-- build/SourceLink.props | 4 +-- nukebuild/_build.csproj | 2 +- .../Models/TreeDataGrid/DragInfo.cs | 24 ++++++----------- .../Primitives/TreeDataGridRow.cs | 26 +++++++++++-------- .../TreeDataGrid.cs | 12 +++++---- 6 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 38cd198f..9d3235a3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,8 +14,8 @@ - 11.0.0 - 11.3.6 + 12.0.1 + 12.0.* diff --git a/build/SourceLink.props b/build/SourceLink.props index 9b767e54..77d49210 100644 --- a/build/SourceLink.props +++ b/build/SourceLink.props @@ -1,4 +1,4 @@ - + true true @@ -19,7 +19,7 @@ - + diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj index e2ecec09..3f0080ce 100644 --- a/nukebuild/_build.csproj +++ b/nukebuild/_build.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/DragInfo.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/DragInfo.cs index f9c31e4b..c9ac82db 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/DragInfo.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/DragInfo.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Avalonia.Input; namespace Avalonia.Controls.Models.TreeDataGrid { @@ -6,32 +7,23 @@ namespace Avalonia.Controls.Models.TreeDataGrid /// Holds information about an automatic row drag/drop operation carried out /// by . /// - public class DragInfo + /// The source of the drag operation/ + /// The indexes being dragged. + public class DragInfo(ITreeDataGridSource source, IEnumerable indexes) { /// - /// Defines the data format in an . + /// Defines the data format for dragging TreeDataGrid rows. /// - public const string DataFormat = "TreeDataGridDragInfo"; - - /// - /// Initializes a new instance of the class. - /// - /// The source of the drag operation/ - /// The indexes being dragged. - public DragInfo(ITreeDataGridSource source, IEnumerable indexes) - { - Source = source; - Indexes = indexes; - } + public static readonly DataFormat Format = DataFormat.CreateInProcessFormat("TreeDataGridDragInfo"); /// /// Gets the that rows are being dragged from. /// - public ITreeDataGridSource Source { get; } + public ITreeDataGridSource Source { get; } = source; /// /// Gets or sets the model indexes of the rows being dragged. /// - public IEnumerable Indexes { get; } + public IEnumerable Indexes { get; } = indexes; } } diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs index 7b60a319..0972b4e6 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridRow.cs @@ -11,7 +11,6 @@ namespace Avalonia.Controls.Primitives public class TreeDataGridRow : TemplatedControl { private const double DragDistance = 3; - private static readonly Point s_InvalidPoint = new(double.NegativeInfinity, double.NegativeInfinity); public static readonly DirectProperty ColumnsProperty = AvaloniaProperty.RegisterDirect( @@ -38,7 +37,7 @@ public class TreeDataGridRow : TemplatedControl private TreeDataGridElementFactory? _elementFactory; private bool _isSelected; private IRows? _rows; - private Point _mouseDownPosition = s_InvalidPoint; + private (Point position, PointerPressedEventArgs eventArgs)? _mouseDownInfo = null; private TreeDataGrid? _treeDataGrid; public IColumns? Columns @@ -144,15 +143,22 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnPointerPressed(PointerPressedEventArgs e) { base.OnPointerPressed(e); - _mouseDownPosition = !e.Handled ? e.GetPosition(this) : s_InvalidPoint; + + if (!e.Handled) + _mouseDownInfo = (e.GetPosition(this), e); } protected override void OnPointerMoved(PointerEventArgs e) { base.OnPointerMoved(e); + if (!_mouseDownInfo.HasValue || + e.Handled) + return; + + var (mouseDownPoint, eventArgs) = _mouseDownInfo.Value; var currentPoint = e.GetCurrentPoint(this); - var delta = currentPoint.Position - _mouseDownPosition; + var delta = currentPoint.Position - mouseDownPoint; var pointerSupportsDrag = currentPoint.Pointer.Type switch { @@ -162,28 +168,26 @@ protected override void OnPointerMoved(PointerEventArgs e) }; if (!pointerSupportsDrag || - e.Handled || - Math.Abs(delta.X) < DragDistance && Math.Abs(delta.Y) < DragDistance || - _mouseDownPosition == s_InvalidPoint) + Math.Abs(delta.X) < DragDistance && Math.Abs(delta.Y) < DragDistance) return; - _mouseDownPosition = s_InvalidPoint; + _mouseDownInfo = default; var presenter = Parent as TreeDataGridRowsPresenter; var owner = presenter?.TemplatedParent as TreeDataGrid; - owner?.RaiseRowDragStarted(e); + owner?.RaiseRowDragStarted(eventArgs); } protected override void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); - _mouseDownPosition = s_InvalidPoint; + _mouseDownInfo = default; } protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e) { base.OnPointerCaptureLost(e); - _mouseDownPosition = s_InvalidPoint; + _mouseDownInfo = default; } protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) diff --git a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs index 1fa94177..b045ffca 100644 --- a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs +++ b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs @@ -519,7 +519,7 @@ internal void RaiseRowPrepared(TreeDataGridRow row, int rowIndex) } } - internal void RaiseRowDragStarted(PointerEventArgs trigger) + internal void RaiseRowDragStarted(PointerPressedEventArgs trigger) { if (_source is null || RowSelection is null) return; @@ -539,10 +539,12 @@ internal void RaiseRowDragStarted(PointerEventArgs trigger) if (allowedEffects != DragDropEffects.None) { - var data = new DataObject(); + var dataTransfer = new DataTransfer(); var info = new DragInfo(_source, RowSelection.SelectedIndexes.ToList()); - data.Set(DragInfo.DataFormat, info); - DragDrop.DoDragDrop(trigger, data, allowedEffects); + var item = new DataTransferItem(); + item.Set(DragInfo.Format, info); + dataTransfer.Add(item); + _ = DragDrop.DoDragDropAsync(trigger, dataTransfer, allowedEffects); } } @@ -683,7 +685,7 @@ private bool CalculateAutoDragDrop( out TreeDataGridRowDropPosition position) { if (!AutoDragDropRows || - e.Data.Get(DragInfo.DataFormat) is not DragInfo di || + e.DataTransfer.TryGetValues(DragInfo.Format)?.FirstOrDefault() is not DragInfo di || _source is null || _source.IsSorted || targetRow is null || From ac218a1a4fd707ba34d67fdcd96fcac70d28a78e Mon Sep 17 00:00:00 2001 From: Fidarit Mullayanov Date: Sun, 19 Apr 2026 19:59:12 +0500 Subject: [PATCH 3/3] fix: build errors after migration --- samples/TreeDataGridDemo/App.axaml.cs | 2 + samples/TreeDataGridDemo/MainWindow.axaml.cs | 2 - .../TreeDataGridDemo/TreeDataGridDemo.csproj | 2 +- .../Experimental/Data/Core/MathWrapper.cs | 52 +++++++++++++++++++ .../Core/SingleSubscriberObservableBase.cs | 4 +- .../Experimental/Data/DataContextRoot.cs | 2 +- .../Data/ParentDataContextRoot.cs | 2 +- .../TreeDataGrid/AnonymousSortableRows.cs | 4 +- .../Models/TreeDataGrid/ColumnBase`1.cs | 6 +-- .../Models/TreeDataGrid/ColumnList.cs | 4 +- .../Models/TreeDataGrid/HierarchicalRows.cs | 4 +- .../TreeDataGrid/ShowExpanderObservable.cs | 2 +- .../Primitives/RealizedStackElements.cs | 4 +- .../Primitives/TreeDataGridCell.cs | 7 ++- .../Primitives/TreeDataGridColumnHeader.cs | 4 +- .../Primitives/TreeDataGridPresenterBase.cs | 6 +-- .../Primitives/TreeDataGridTemplateCell.cs | 2 +- .../TreeDataGridRowSelectionModel.cs | 4 +- .../TreeDataGrid.cs | 6 +-- ...valonia.Controls.TreeDataGrid.Tests.csproj | 4 +- .../TreeDataGridTests_Flat.cs | 2 +- 21 files changed, 88 insertions(+), 37 deletions(-) create mode 100644 src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/MathWrapper.cs diff --git a/samples/TreeDataGridDemo/App.axaml.cs b/samples/TreeDataGridDemo/App.axaml.cs index cc3d1f15..b2da5c73 100644 --- a/samples/TreeDataGridDemo/App.axaml.cs +++ b/samples/TreeDataGridDemo/App.axaml.cs @@ -14,6 +14,8 @@ public override void Initialize() public override void OnFrameworkInitializationCompleted() { + this.AttachDeveloperTools(); + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { desktop.MainWindow = new MainWindow(); diff --git a/samples/TreeDataGridDemo/MainWindow.axaml.cs b/samples/TreeDataGridDemo/MainWindow.axaml.cs index 4a1bcdd0..29d82a19 100644 --- a/samples/TreeDataGridDemo/MainWindow.axaml.cs +++ b/samples/TreeDataGridDemo/MainWindow.axaml.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using Avalonia; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; @@ -20,7 +19,6 @@ public partial class MainWindow : Window public MainWindow() { InitializeComponent(); - this.AttachDevTools(); DataContext = new MainWindowViewModel(); _tabs = this.FindControl("tabs"); diff --git a/samples/TreeDataGridDemo/TreeDataGridDemo.csproj b/samples/TreeDataGridDemo/TreeDataGridDemo.csproj index eddf4440..f7ffcce9 100644 --- a/samples/TreeDataGridDemo/TreeDataGridDemo.csproj +++ b/samples/TreeDataGridDemo/TreeDataGridDemo.csproj @@ -18,9 +18,9 @@ - + diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/MathWrapper.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/MathWrapper.cs new file mode 100644 index 00000000..9508ca96 --- /dev/null +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/MathWrapper.cs @@ -0,0 +1,52 @@ +using System; + +namespace Avalonia.Experimental.Data.Core; + +/// +/// Provides math utilities not provided in System.Math. +/// +internal class MathWrapper +{ + // smallest such that 1.0+DoubleEpsilon != 1.0 + internal const double DoubleEpsilon = 2.2204460492503131e-016; + + internal const float FloatEpsilon = 1.192092896e-07F; + + /// + /// AreClose - Returns whether or not two doubles are "close". That is, whether or + /// not they are within epsilon of each other. + /// + /// The first double to compare. + /// The second double to compare. + public static bool AreClose(double value1, double value2) + { + //in case they are Infinities (then epsilon check does not work) + if (value1 == value2) + return true; + double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DoubleEpsilon; + double delta = value1 - value2; + return (-eps < delta) && (eps > delta); + } + + /// + /// GreaterThan - Returns whether or not the first double is greater than the second double. + /// That is, whether or not the first is strictly greater than *and* not within epsilon of + /// the other number. + /// + /// The first double to compare. + /// The second double to compare. + public static bool GreaterThan(double value1, double value2) + { + return (value1 > value2) && !AreClose(value1, value2); + } + + /// + /// IsZero - Returns whether or not the double is "close" to 0. Same as AreClose(double, 0), + /// but this is faster. + /// + /// The double to compare to 0. + public static bool IsZero(double value) + { + return Math.Abs(value) < 10.0 * DoubleEpsilon; + } +} diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/SingleSubscriberObservableBase.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/SingleSubscriberObservableBase.cs index aa9e0919..c99c6fb7 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/SingleSubscriberObservableBase.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/Core/SingleSubscriberObservableBase.cs @@ -1,7 +1,7 @@ -using System; +using System; using Avalonia.Threading; -namespace Avalonia.Controls.Experimental.Data.Core; +namespace Avalonia.Experimental.Data.Core; internal abstract class SingleSubscriberObservableBase : IObservable, IDisposable { diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/DataContextRoot.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/DataContextRoot.cs index cda65e52..8a6d17fe 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/DataContextRoot.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/DataContextRoot.cs @@ -1,4 +1,4 @@ -using Avalonia.Controls.Experimental.Data.Core; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Experimental.Data { diff --git a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ParentDataContextRoot.cs b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ParentDataContextRoot.cs index eb19ded9..05209d24 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ParentDataContextRoot.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Experimental/Data/ParentDataContextRoot.cs @@ -1,4 +1,4 @@ -using Avalonia.Controls.Experimental.Data.Core; +using Avalonia.Experimental.Data.Core; using Avalonia.VisualTree; namespace Avalonia.Experimental.Data diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousSortableRows.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousSortableRows.cs index 72c209eb..6444c0eb 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousSortableRows.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/AnonymousSortableRows.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using Avalonia.Controls.Utils; -using Avalonia.Utilities; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Controls.Models.TreeDataGrid { @@ -83,7 +83,7 @@ public void Dispose() { // Rows in an AnonymousSortableRows collection have Auto height so we only // know the start position of the first row. - if (MathUtilities.IsZero(y)) + if (MathWrapper.IsZero(y)) return (0, 0); return (-1, -1); } diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`1.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`1.cs index f1f8ec67..16b7142d 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`1.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnBase`1.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using Avalonia.Data; using Avalonia.Experimental.Data; -using Avalonia.Utilities; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Controls.Models.TreeDataGrid { @@ -156,7 +156,7 @@ void IUpdateColumnLayout.CalculateStarWidth(double availableWidth, double totalS var width = (availableWidth / totalStars) * Width.Value; _starWidth = CoerceActualWidth(width); - _starWidthWasConstrained = !MathUtilities.AreClose(_starWidth, width); + _starWidthWasConstrained = !MathWrapper.AreClose(_starWidth, width); } bool IUpdateColumnLayout.CommitActualWidth() @@ -184,7 +184,7 @@ bool IUpdateColumnLayout.CommitActualWidth() return false; } - return !MathUtilities.AreClose(oldWidth, ActualWidth); + return !MathWrapper.AreClose(oldWidth, ActualWidth); } void IUpdateColumnLayout.SetWidth(GridLength width) => SetWidth(width); diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnList.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnList.cs index 55495176..28625543 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnList.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ColumnList.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using Avalonia.Collections; -using Avalonia.Utilities; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Controls.Models.TreeDataGrid { @@ -160,7 +160,7 @@ private void UpdateColumnSizes() // If the width of any star columns was constrained by their min/max size, and we // actually had any space to distribute between star columns, then we need to update // the star width for the non-constrained columns. - if (starWidthWasConstrained && MathUtilities.GreaterThan(availableSpace, 0)) + if (starWidthWasConstrained && MathWrapper.GreaterThan(availableSpace, 0)) { for (var i = 0; i < Count; ++i) { diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRows.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRows.cs index c8b8bb33..f45c1408 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRows.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/HierarchicalRows.cs @@ -2,7 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; -using Avalonia.Utilities; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Controls.Models.TreeDataGrid { @@ -130,7 +130,7 @@ public void Collapse(IndexPath index) /// public (int index, double y) GetRowAt(double y) { - if (MathUtilities.IsZero(y)) + if (MathWrapper.IsZero(y)) return (0, 0); return (-1, -1); } diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ShowExpanderObservable.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ShowExpanderObservable.cs index 3ea0159f..6d73d497 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ShowExpanderObservable.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/ShowExpanderObservable.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; -using Avalonia.Controls.Experimental.Data.Core; using Avalonia.Data; using Avalonia.Experimental.Data; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Controls.Models.TreeDataGrid { diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/RealizedStackElements.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/RealizedStackElements.cs index 836c81fb..1c1fcb26 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/RealizedStackElements.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/RealizedStackElements.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using Avalonia.Controls.Models.TreeDataGrid; -using Avalonia.Utilities; +using Avalonia.Experimental.Data.Core; namespace Avalonia.Controls.Primitives { @@ -128,7 +128,7 @@ public void Add(int index, Control element, double u, double sizeU) return (-1, 0); // If we're at 0 then display the first item. - if (MathUtilities.IsZero(viewportStartU)) + if (MathWrapper.IsZero(viewportStartU)) return (0, 0); if (_sizes is not null && !_startUUnstable) diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs index 3e149cb6..524ecf37 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs @@ -4,7 +4,6 @@ using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Selection; using Avalonia.Input; -using Avalonia.Interactivity; using Avalonia.LogicalTree; using Avalonia.VisualTree; @@ -143,7 +142,7 @@ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) _treeDataGrid.RaiseCellPrepared(this, ColumnIndex, RowIndex); } - protected override void OnLostFocus(RoutedEventArgs e) + protected override void OnLostFocus(FocusChangedEventArgs e) { base.OnLostFocus(e); @@ -163,7 +162,7 @@ protected override Size MeasureOverride(Size availableSize) return result; } - protected virtual void OnDoubleTapped(TappedEventArgs e) + protected override void OnDoubleTapped(TappedEventArgs e) { if (Model is not null && !e.Handled && @@ -238,7 +237,7 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e) IsEnabledEditGesture(BeginEditGestures.Tap, Model.EditGestures)) { var point = e.GetCurrentPoint(this); - var settings = TopLevel.GetTopLevel(this)?.PlatformSettings; + var settings = this.GetPlatformSettings(); var tapSize = settings?.GetTapSize(point.Pointer.Type) ?? new Size(4, 4); var tapRect = new Rect(_pressedPoint, new Size()) .Inflate(new Thickness(tapSize.Width, tapSize.Height)); diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs index c9cf22de..e1d11bb7 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridColumnHeader.cs @@ -1,8 +1,8 @@ using System; using System.ComponentModel; using Avalonia.Controls.Models.TreeDataGrid; +using Avalonia.Experimental.Data.Core; using Avalonia.Input; -using Avalonia.Utilities; namespace Avalonia.Controls.Primitives { @@ -160,7 +160,7 @@ private void OnOwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEvent private void ResizerDragDelta(object? sender, VectorEventArgs e) { - if (_columns is null || _model is null || MathUtilities.IsZero(e.Vector.X)) + if (_columns is null || _model is null || MathWrapper.IsZero(e.Vector.X)) return; var pixelWidth = _model.Width.IsAbsolute ? _model.Width.Value : Bounds.Width; diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs index 54573228..6458716c 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridPresenterBase.cs @@ -4,10 +4,10 @@ using System.Data; using System.Diagnostics; using System.Linq; +using Avalonia.Experimental.Data.Core; using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.LogicalTree; -using Avalonia.Utilities; using Avalonia.VisualTree; using CollectionExtensions = Avalonia.Controls.Models.TreeDataGrid.CollectionExtensions; @@ -457,8 +457,8 @@ protected virtual void OnEffectiveViewportChanged(object? sender, EffectiveViewp var newViewportStart = vertical ? Viewport.Top : Viewport.Left; var newViewportEnd = vertical ? Viewport.Bottom : Viewport.Right; - if (!MathUtilities.AreClose(oldViewportStart, newViewportStart) || - !MathUtilities.AreClose(oldViewportEnd, newViewportEnd)) + if (!MathWrapper.AreClose(oldViewportStart, newViewportStart) || + !MathWrapper.AreClose(oldViewportEnd, newViewportEnd)) { InvalidateMeasure(); } diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTemplateCell.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTemplateCell.cs index 0431929c..4db78f10 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTemplateCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTemplateCell.cs @@ -127,7 +127,7 @@ protected override void OnDataContextChanged(EventArgs e) } } - protected override void OnLostFocus(RoutedEventArgs e) + protected override void OnLostFocus(FocusChangedEventArgs e) { if (EndEditIfFocusLost()) { diff --git a/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridRowSelectionModel.cs b/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridRowSelectionModel.cs index dabbbe4f..80780edb 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridRowSelectionModel.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridRowSelectionModel.cs @@ -391,8 +391,8 @@ private void PointerSelect(TreeDataGrid sender, TreeDataGridRow row, PointerEven { var point = e.GetCurrentPoint(sender); - var commandModifiers = TopLevel.GetTopLevel(sender)?.PlatformSettings?.HotkeyConfiguration.CommandModifiers; - var toggleModifier = commandModifiers is not null && e.KeyModifiers.HasFlag(commandModifiers); + var commandModifiers = sender.GetPlatformSettings()?.HotkeyConfiguration.CommandModifiers; + var toggleModifier = commandModifiers.HasValue && e.KeyModifiers.HasFlag(commandModifiers.Value); var isRightButton = point.Properties.PointerUpdateKind is PointerUpdateKind.RightButtonPressed or PointerUpdateKind.RightButtonReleased; diff --git a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs index b045ffca..c38457aa 100644 --- a/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs +++ b/src/Avalonia.Controls.TreeDataGrid/TreeDataGrid.cs @@ -7,10 +7,10 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Selection; using Avalonia.Controls.Shapes; +using Avalonia.Experimental.Data.Core; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Threading; -using Avalonia.Utilities; using Avalonia.VisualTree; namespace Avalonia.Controls @@ -791,13 +791,13 @@ row is not null && private void OnScrollChanged(object? sender, ScrollChangedEventArgs e) { - if (Scroll is not null && _headerScroll is not null && !MathUtilities.IsZero(e.OffsetDelta.X)) + if (Scroll is not null && _headerScroll is not null && !MathWrapper.IsZero(e.OffsetDelta.X)) _headerScroll.Offset = _headerScroll.Offset.WithX(Scroll.Offset.X); } private void OnHeaderScrollChanged(object? sender, ScrollChangedEventArgs e) { - if (Scroll is not null && _headerScroll is not null && !MathUtilities.IsZero(e.OffsetDelta.X)) + if (Scroll is not null && _headerScroll is not null && !MathWrapper.IsZero(e.OffsetDelta.X)) Scroll.Offset = Scroll.Offset.WithX(_headerScroll.Offset.X); } diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/Avalonia.Controls.TreeDataGrid.Tests.csproj b/tests/Avalonia.Controls.TreeDataGrid.Tests/Avalonia.Controls.TreeDataGrid.Tests.csproj index 792a5b65..3766cb05 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/Avalonia.Controls.TreeDataGrid.Tests.csproj +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/Avalonia.Controls.TreeDataGrid.Tests.csproj @@ -7,12 +7,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/TreeDataGridTests_Flat.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/TreeDataGridTests_Flat.cs index 11b7e997..f4b636e3 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/TreeDataGridTests_Flat.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/TreeDataGridTests_Flat.cs @@ -424,7 +424,7 @@ public void Header_Column_Indexes_Are_Updated_When_Columns_Are_Updated() source.Columns.Add(movedColumn); - var root = (TestWindow)target.GetVisualRoot()!; + var root = (TestWindow)target.Parent!; root.UpdateLayout(); Dispatcher.UIThread.RunJobs();