From 5b307f653d6f17d4314217786c3e562897f9f68d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 16 Oct 2015 00:24:46 +0200 Subject: [PATCH] Fix spurious selection changes. In SelectingItemsControl. This was causing TabControls with transitions to break. --- .../Primitives/SelectingItemsControl.cs | 19 ++++++++++++---- .../SelectingItemsControlTests_Multiple.cs | 22 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs index 86f1603a6e..f1de2dea5f 100644 --- a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs @@ -82,6 +82,7 @@ namespace Perspex.Controls.Primitives private object _selectedItem; private IList _selectedItems; private bool _ignoreContainerSelectionChanged; + private bool _syncingSelectedItems; private IList _clearSelectedItemsAfterDataContextChanged; /// @@ -150,8 +151,10 @@ namespace Perspex.Controls.Primitives { if (SelectedItems.Count != 1 || SelectedItems[0] != effective) { + _syncingSelectedItems = true; SelectedItems.Clear(); SelectedItems.Add(effective); + _syncingSelectedItems = false; } } else if (SelectedItems.Count > 0) @@ -283,6 +286,7 @@ namespace Perspex.Controls.Primitives } } + /// protected override void OnDataContextFinishedChanging() { if (_clearSelectedItemsAfterDataContextChanged == SelectedItems) @@ -661,7 +665,10 @@ namespace Perspex.Controls.Primitives case NotifyCollectionChangedAction.Remove: if (SelectedItems.Count == 0) { - SelectedIndex = -1; + if (!_syncingSelectedItems) + { + SelectedIndex = -1; + } } else { @@ -679,7 +686,11 @@ namespace Perspex.Controls.Primitives MarkContainerSelected(item, false); } - SelectedIndex = -1; + if (!_syncingSelectedItems) + { + SelectedIndex = -1; + } + SelectedItemsAdded(SelectedItems); break; @@ -694,7 +705,7 @@ namespace Perspex.Controls.Primitives MarkItemSelected(item, true); } - if (SelectedItem != SelectedItems[0]) + if (SelectedItem != SelectedItems[0] && !_syncingSelectedItems) { var oldItem = SelectedItem; var oldIndex = SelectedIndex; @@ -723,7 +734,7 @@ namespace Perspex.Controls.Primitives MarkItemSelected(item, true); } - if (SelectedItem == null) + if (SelectedItem == null && !_syncingSelectedItems) { var index = IndexOf(Items, items[0]); diff --git a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs index 85f275ad80..002c67f506 100644 --- a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs +++ b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs @@ -1,6 +1,7 @@ // Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -355,6 +356,27 @@ namespace Perspex.Controls.UnitTests.Primitives Assert.Equal(new[] { "baz", "qux", "qiz" }, target.SelectedItems.Cast().ToList()); } + [Fact] + public void Suprious_SelectedIndex_Changes_Should_Not_Be_Triggered() + { + var target = new TestSelector + { + Items = new[] { "foo", "bar", "baz" }, + Template = Template(), + }; + + target.ApplyTemplate(); + + var selectedIndexes = new List(); + target.GetObservable(TestSelector.SelectedIndexProperty).Subscribe(x => selectedIndexes.Add(x)); + + target.SelectedItems = new PerspexList { "bar", "baz" }; + target.SelectedItem = "foo"; + + Assert.Equal(0, target.SelectedIndex); + Assert.Equal(new[] { -1, 1, 0 }, selectedIndexes); + } + /// /// Tests a problem discovered with ListBox with selection. ///