diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs index f2a09b815e..43246c8e9d 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Avalonia.Media; using Avalonia.Platform; using Avalonia.Threading; @@ -258,14 +259,25 @@ namespace Avalonia.Rendering.SceneGraph } else if (visualChildren.Count > 1) { - var sortedChildren = new IVisual[visualChildren.Count]; - visualChildren.CopyTo(sortedChildren, 0); + var count = visualChildren.Count; + var sortedChildren = new (IVisual visual, int index)[count]; - Array.Sort(sortedChildren, ZIndexComparer.ComparisonInstance); + for (var i = 0; i < count; i++) + { + sortedChildren[i] = (visualChildren[i], i); + } + + // Regular Array.Sort is unstable, we need to provide indices as well to avoid reshuffling elements. + Array.Sort(sortedChildren, (lhs, rhs) => + { + var result = ZIndexComparer.Instance.Compare(lhs.visual, rhs.visual); + + return result == 0 ? lhs.index.CompareTo(rhs.index) : result; + }); foreach (var child in sortedChildren) { - var childNode = GetOrCreateChildNode(scene, child, node); + var childNode = GetOrCreateChildNode(scene, child.Item1, node); Update(context, scene, (VisualNode)childNode, clip, forceRecurse); } }