Browse Source

Fix issue #11006 by correcting SelectionChanged event to be fired AFTER (not before) raising Prop… (#13503)

* fix selectedchanged event to be fired AFTER (not before) raising Property changed notification

* Unit test added
lnxon 1 year ago
parent
commit
40b73a661f

+ 32 - 30
src/Avalonia.Controls/Selection/SelectionModel.cs

@@ -674,7 +674,39 @@ namespace Avalonia.Controls.Selection
                         indexesChanged |= CommitDeselect(range.Begin, range.End) > 0;
                     }
                 }
+                
+                
+
+                if (raisePropertyChanged)
+                {
+                    if (oldSelectedIndex != _selectedIndex)
+                    {
+                        indexesChanged = true;
+                        RaisePropertyChanged(nameof(SelectedIndex));
+                    }
+
+                    if (oldSelectedIndex != _selectedIndex || operation.IsSourceUpdate)
+                    {
+                        RaisePropertyChanged(nameof(SelectedItem));
+                    }
 
+                    if (oldAnchorIndex != _anchorIndex)
+                    {
+                        indexesChanged = true;
+                        RaisePropertyChanged(nameof(AnchorIndex));
+                    }
+
+                    if (indexesChanged)
+                    {
+                        RaisePropertyChanged(nameof(SelectedIndexes));
+                    }
+
+                    if (indexesChanged || operation.IsSourceUpdate)
+                    {
+                        RaisePropertyChanged(nameof(SelectedItems));
+                    }
+                } 
+                
                 if (SelectionChanged is not null || _untypedSelectionChanged is not null)
                 {
                     IReadOnlyList<IndexRange>? deselected = operation.DeselectedRanges;
@@ -715,36 +747,6 @@ namespace Avalonia.Controls.Selection
                         _untypedSelectionChanged?.Invoke(this, e);
                     }
                 }
-
-                if (raisePropertyChanged)
-                {
-                    if (oldSelectedIndex != _selectedIndex)
-                    {
-                        indexesChanged = true;
-                        RaisePropertyChanged(nameof(SelectedIndex));
-                    }
-
-                    if (oldSelectedIndex != _selectedIndex || operation.IsSourceUpdate)
-                    {
-                        RaisePropertyChanged(nameof(SelectedItem));
-                    }
-
-                    if (oldAnchorIndex != _anchorIndex)
-                    {
-                        indexesChanged = true;
-                        RaisePropertyChanged(nameof(AnchorIndex));
-                    }
-
-                    if (indexesChanged)
-                    {
-                        RaisePropertyChanged(nameof(SelectedIndexes));
-                    }
-
-                    if (indexesChanged || operation.IsSourceUpdate)
-                    {
-                        RaisePropertyChanged(nameof(SelectedItems));
-                    }
-                }
             }
             finally
             {

+ 50 - 0
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@@ -2224,6 +2224,56 @@ namespace Avalonia.Controls.UnitTests.Primitives
 
             Assert.Equal(0, selectedItemChangedRaised);
         }
+        
+        [Fact]
+        public void Should_First_Raise_Property_Changed_Notification_Then_Fire_Selection_Changed_Event()
+        {
+            using var _ = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+            // Issue #11006
+            var items = new ObservableCollection<string>();
+            
+            var vm = new SelectionViewModel
+            {
+                SelectedItem = "" ,
+            };
+            
+            var theListBox = new ListBox
+            {
+                DataContext = vm,
+                Template = Template(), 
+                ItemsSource = items, 
+                SelectionMode = SelectionMode.AlwaysSelected,
+                [!ListBox.SelectedItemProperty] = new Binding("SelectedItem"),
+            };
+            
+            var target = new TextBox
+            {
+                Text = "",
+            };
+
+            Prepare(theListBox);
+            
+            items.Add("Default");
+            items.Add("First");
+            items.Add("Second");
+            items.Add("Third");
+            
+            theListBox.SelectionChanged += (s, e) =>
+            {
+                target.Text = (string)vm.SelectedItem;
+            };
+            
+            theListBox.SelectedIndex = 1;
+            Assert.Equal("First", target.Text);
+
+            theListBox.SelectedIndex = 2;
+            Assert.Equal("Second", target.Text);
+
+            theListBox.SelectedIndex = 3;
+            Assert.Equal("Third", target.Text);
+
+        }
 
         private static IDisposable Start()
         {