diff --git a/src/NexusMods.App.UI/Controls/TreeDataGrid/CustomElementFactory.cs b/src/NexusMods.App.UI/Controls/TreeDataGrid/CustomElementFactory.cs index 0e2428d052..bf271c358e 100644 --- a/src/NexusMods.App.UI/Controls/TreeDataGrid/CustomElementFactory.cs +++ b/src/NexusMods.App.UI/Controls/TreeDataGrid/CustomElementFactory.cs @@ -1,4 +1,6 @@ +using System.Text; using Avalonia.Controls; +using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Primitives; namespace NexusMods.App.UI.Controls; @@ -9,31 +11,70 @@ namespace NexusMods.App.UI.Controls; /// public class CustomElementFactory : TreeDataGridElementFactory { + // NOTE(erri120): Used in styles, don't change! + private const string RootRowClass = "RootRow"; + protected override Control CreateElement(object? data) { var element = base.CreateElement(data); - if (data is ICustomCell customCell) + switch (data) { - element.Classes.Add(customCell.Id); - if (customCell.IsRoot) - { - element.Classes.Add("RootRow"); - } + // Add RootRowClass to root rows + case IIndentedRow { Indent: 0 }: + element.Classes.Add(RootRowClass); + break; + // Add Id to custom cells + case ICustomCell customCell: + element.Classes.Add(customCell.Id); + break; } return element; } - + protected override string GetDataRecycleKey(object? data) { - // TODO(erri120): I think we need to implement this, otherwise cells for one column get put in another column - return base.GetDataRecycleKey(data); + // NOTE(Al12rs): Cell recycling breaks Id and RootRowClass styling, since these are not reapplied when the cell is reused. + // To fix this, we restrict the recycling to only reuse cells with matching Id and RootRowClass. + // This is done by appending the Id and RootRowClass to the base key. + + switch (data) + { + case IIndentedRow: + var rowKey = $"{base.GetDataRecycleKey(data)}|{RootRowClass}"; + return string.Intern(rowKey); + case ICustomCell customCell: + { + // NOTE(Al12rs): the keys generated here should match the ones in GetElementRecycleKey, ensure order and format is the same + var cellKey = $"{base.GetDataRecycleKey(data)}|{customCell.Id}"; + return string.Intern(cellKey); + } + default: + return base.GetDataRecycleKey(data); + } } protected override string GetElementRecycleKey(Control element) { - // TODO(erri120): I think we need to implement this, otherwise cells for one column get put in another column - return base.GetElementRecycleKey(element); + // NOTE(Al12rs): Cell recycling breaks Id and RootRowClass styling, since these are not reapplied when the cell is reused. + // To fix this, we restrict the recycling to only reuse cells with matching Id and RootRowClass. + // This is done by appending the Id and RootRowClass to the base key. + + var sb = new StringBuilder(value: base.GetElementRecycleKey(element)); + + if (element is not TreeDataGridCell or TreeDataGridRow) + return string.Intern(sb.ToString()); + + // NOTE(Al12rs): Order here should match the insertion order in CreateElement, first the id, then the RootRowClass + foreach (var className in element.Classes) + { + if (className is null) continue; + if (className.StartsWith(':')) continue; + sb.Append($"|{className}"); + } + + var key = string.Intern(sb.ToString()); + return key; } } diff --git a/src/Themes/NexusMods.Themes.NexusFluentDark/Styles/Controls/TreeDataGrid/TreeDataGridStyles.axaml b/src/Themes/NexusMods.Themes.NexusFluentDark/Styles/Controls/TreeDataGrid/TreeDataGridStyles.axaml index 3b241c7862..98d8273c0c 100644 --- a/src/Themes/NexusMods.Themes.NexusFluentDark/Styles/Controls/TreeDataGrid/TreeDataGridStyles.axaml +++ b/src/Themes/NexusMods.Themes.NexusFluentDark/Styles/Controls/TreeDataGrid/TreeDataGridStyles.axaml @@ -34,19 +34,18 @@ - - + - + - + - + + + + - + @@ -142,19 +147,19 @@ BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" Padding="{TemplateBinding Indent, Converter={x:Static converters1:TreeDataGridIndentToPaddingConverter.Instance}}"> - + - - + + Background="{StaticResource SurfaceTranslucentMidBrush}" /> - + + IsVisible="{TemplateBinding ShowExpander}" /> @@ -171,7 +176,7 @@ - + - + - + @@ -206,27 +211,36 @@ - - + + + + + + + + + + - + - - - + + - -