diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 1a9042a25b..2cf8d941ca 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -307,12 +307,14 @@ namespace Avalonia.Controls private void SelectSingleItem(object item) { + var oldValue = _selectedItem; _syncingSelectedItems = true; - SelectedItems.Clear(); + SelectedItems.Clear(); + _selectedItem = item; SelectedItems.Add(item); _syncingSelectedItems = false; - SetAndRaise(SelectedItemProperty, ref _selectedItem, item); + RaisePropertyChanged(SelectedItemProperty, oldValue, _selectedItem); } /// diff --git a/src/tools/DevGenerators/CompositionGenerator/Generator.cs b/src/tools/DevGenerators/CompositionGenerator/Generator.cs index dfc8b45579..ced2cb369c 100644 --- a/src/tools/DevGenerators/CompositionGenerator/Generator.cs +++ b/src/tools/DevGenerators/CompositionGenerator/Generator.cs @@ -170,21 +170,26 @@ namespace Avalonia.SourceGenerator.CompositionGenerator if (manual.ServerName != null) serverPropertyType = manual.ServerName + (isNullable ? "?" : ""); } - if (animatedServer) server = server.AddMembers( DeclareField(serverPropertyType, fieldName), PropertyDeclaration(ParseTypeName(serverPropertyType), prop.Name) .AddModifiers(SyntaxKind.PublicKeyword) - .WithExpressionBody(ArrowExpressionClause( - InvocationExpression(IdentifierName("GetAnimatedValue"), - ArgumentList(SeparatedList(new[]{ - Argument(IdentifierName(CompositionPropertyField(prop))), - Argument(null, Token(SyntaxKind.RefKeyword), IdentifierName(fieldName)) - } - ))))) - .WithSemicolonToken(Semicolon()) - ); + .AddAccessorListAccessors( + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("GetAnimatedValue"), + ArgumentList(SeparatedList(new[] + { + Argument(IdentifierName(CompositionPropertyField(prop))), + Argument(null, Token(SyntaxKind.RefKeyword), + IdentifierName(fieldName)) + } + ))))).WithSemicolonToken(Semicolon()), + AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) + .WithExpressionBody(ArrowExpressionClause( + ParseExpression($"SetAnimatedValue({CompositionPropertyField(prop)}, out {PropertyBackingFieldName(prop)}, value)"))) + .WithSemicolonToken(Semicolon()))); else { server = server @@ -508,9 +513,7 @@ var changed = reader.Read<{ChangedFieldsTypeName(cl)}>(); code += $@" if((changed & {changedFieldsType}.{prop.Name}) == {changedFieldsType}.{prop.Name}) "; - if (prop.Animated) - code += $"SetAnimatedValue({CompositionPropertyField(prop)}, out {PropertyBackingFieldName(prop)}, {readValueCode});"; - else code += $"{prop.Name} = {readValueCode};"; + code += $"{prop.Name} = {readValueCode};"; return body.AddStatements(ParseStatement(code)); } diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 129720d00a..3ca70f96cc 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -722,6 +722,33 @@ namespace Avalonia.Controls.UnitTests Assert.True(called); } + [Fact] + public void SelectedItem_Should_Be_Valid_When_SelectedItemChanged_Event_Raised() + { + using var app = Start(); + var data = CreateTestTreeData(); + var target = CreateTarget(data: data); + + var item = data[0].Children[1].Children[0]; + var container = Assert.IsType(target.TreeContainerFromItem(item)); + + Assert.NotNull(container); + + var called = false; + target.SelectionChanged += (s, e) => + { + Assert.Same(item, e.AddedItems[0]); + Assert.Same(item, target.SelectedItem); + called = true; + }; + + _mouse.Click(container); + + Assert.Equal(item, target.SelectedItem); + Assert.True(container.IsSelected); + Assert.True(called); + } + [Fact] public void Bound_SelectedItem_Should_Not_Be_Cleared_when_Changing_Selection() { @@ -756,7 +783,7 @@ namespace Avalonia.Controls.UnitTests using var app = Start(); var data = CreateTestTreeData(); var target = CreateTarget(data: data, expandAll: false); - + target.SelectedItem = data[0].Children[1]; var rootItem = Assert.IsType(target.ContainerFromIndex(0));