diff --git a/src/Toolkit/Toolkit.Maui/BookmarksView/BookmarksView.cs b/src/Toolkit/Toolkit.Maui/BookmarksView/BookmarksView.cs index d7c3b2bc7..59342b348 100644 --- a/src/Toolkit/Toolkit.Maui/BookmarksView/BookmarksView.cs +++ b/src/Toolkit/Toolkit.Maui/BookmarksView/BookmarksView.cs @@ -14,7 +14,6 @@ // * limitations under the License. // ******************************************************************************/ using Esri.ArcGISRuntime.Mapping; -using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; namespace Esri.ArcGISRuntime.Toolkit.Maui; @@ -57,10 +56,6 @@ public BookmarksView() { ItemTemplate = DefaultDataTemplate; ControlTemplate = DefaultControlTemplate; -#if ANDROID - // This Fixes a bug with Android adding item couple of times when new Bookmark is added to BookmarkCollection. - _dataSource.CollectionChanged += OnBookmarksCollectionChanged; -#endif } /// @@ -69,6 +64,13 @@ public BookmarksView() protected override void OnApplyTemplate() { base.OnApplyTemplate(); + + var collectionView = (CollectionView)GetTemplateChild(_presentingViewName); + if (collectionView is CollectionView view) + { + view.SelectionChanged -= Internal_bookmarkSelected; + view.SelectionChanged += Internal_bookmarkSelected; + } UpdatePresentingView(); } @@ -146,8 +148,8 @@ private static void GeoViewChanged(BindableObject sender, object? oldValue, obje /// private static void ItemTemplateChanged(BindableObject sender, object? oldValue, object? newValue) { - BookmarksView bookmarkView = (BookmarksView)sender; - bookmarkView.UpdatePresentingView(); + BookmarksView bookmarksView = (BookmarksView)sender; + bookmarksView.UpdatePresentingView(); } /// @@ -184,22 +186,11 @@ private void Internal_bookmarkSelected(object? sender, SelectionChangedEventArgs private void UpdatePresentingView() { - var collection = (CollectionView)GetTemplateChild(_presentingViewName); - if (collection != null) - { - collection.SelectionChanged -= Internal_bookmarkSelected; - collection.SelectionChanged += Internal_bookmarkSelected; - collection.ItemTemplate = null; - collection.ItemTemplate = ItemTemplate; - collection.ItemsSource = _dataSource; - } - } - - private void OnBookmarksCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - if (e.Action is NotifyCollectionChangedAction.Add) + var collectionView = (CollectionView)GetTemplateChild(_presentingViewName); + if (collectionView is CollectionView view) { - UpdatePresentingView(); + view.ItemTemplate = ItemTemplate; + view.ItemsSource = _dataSource; } } diff --git a/src/Toolkit/Toolkit/UI/Controls/BookmarksView/BookmarksViewDataSource.cs b/src/Toolkit/Toolkit/UI/Controls/BookmarksView/BookmarksViewDataSource.cs index a811939c2..fb259e718 100644 --- a/src/Toolkit/Toolkit/UI/Controls/BookmarksView/BookmarksViewDataSource.cs +++ b/src/Toolkit/Toolkit/UI/Controls/BookmarksView/BookmarksViewDataSource.cs @@ -38,6 +38,9 @@ namespace Esri.ArcGISRuntime.Toolkit.UI.Controls internal class BookmarksViewDataSource : IList, INotifyCollectionChanged, INotifyPropertyChanged, IList { private GeoView? _geoView; + private WeakEventListener? _geoViewBookmarksListener; + private WeakEventListener? _geoViewLoadListener; + private new WeakEventListener? _overrideListListener; private IList? _overrideList; private IList ActiveBookmarkList @@ -93,10 +96,13 @@ public void SetOverrideList(IEnumerable? bookmarks) // Subscribe to events if applicable if (bookmarks is INotifyCollectionChanged iCollectionChanged) { - var listener = new WeakEventListener(this, iCollectionChanged); - listener.OnEventAction = static (instance, source, eventArgs) => instance.HandleOverrideListCollectionChanged(source, eventArgs); - listener.OnDetachAction = static (instance, source, weakEventListener) => source.CollectionChanged -= weakEventListener.OnEvent; - iCollectionChanged.CollectionChanged += listener.OnEvent; + _overrideListListener?.Detach(); + _overrideListListener = new WeakEventListener(this, iCollectionChanged) + { + OnEventAction = static (instance, source, eventArgs) => instance.HandleOverrideListCollectionChanged(source, eventArgs), + OnDetachAction = static (instance, source, weakEventListener) => source.CollectionChanged -= weakEventListener.OnEvent + }; + iCollectionChanged.CollectionChanged += _overrideListListener.OnEvent; } } @@ -188,13 +194,16 @@ private void GeoView_PropertyChanged(object? sender, PropertyChangedEventArgs e) private void GeoViewDocumentChanged(object? sender, object? e) { + _geoViewLoadListener?.Detach(); if (_geoView is MapView mv && mv.Map is ILoadable mapLoadable) { // Listen for load completion - var listener = new WeakEventListener(this, mapLoadable); - listener.OnEventAction = static (instance, source, eventArgs) => instance.Doc_Loaded(source, eventArgs); - listener.OnDetachAction = static (instance, source, weakEventListener) => source.Loaded -= weakEventListener.OnEvent; - mapLoadable.Loaded += listener.OnEvent; + _geoViewLoadListener = new WeakEventListener(this, mapLoadable) + { + OnEventAction = static (instance, source, eventArgs) => instance.Doc_Loaded(source, eventArgs), + OnDetachAction = static (instance, source, weakEventListener) => source.Loaded -= weakEventListener.OnEvent + }; + mapLoadable.Loaded += _geoViewLoadListener.OnEvent; // Ensure event is raised even if already loaded _ = mv.Map.RetryLoadAsync(); @@ -202,10 +211,12 @@ private void GeoViewDocumentChanged(object? sender, object? e) else if (_geoView is SceneView sv && sv.Scene is ILoadable sceneLoadable) { // Listen for load completion - var listener = new WeakEventListener(this, sceneLoadable); - listener.OnEventAction = static (instance, source, eventArgs) => instance.Doc_Loaded(source, eventArgs); - listener.OnDetachAction = static (instance, source, weakEventListener) => source.Loaded -= weakEventListener.OnEvent; - sceneLoadable.Loaded += listener.OnEvent; + _geoViewLoadListener = new WeakEventListener(this, sceneLoadable) + { + OnEventAction = static (instance, source, eventArgs) => instance.Doc_Loaded(source, eventArgs), + OnDetachAction = static (instance, source, weakEventListener) => source.Loaded -= weakEventListener.OnEvent + }; + sceneLoadable.Loaded += _geoViewLoadListener.OnEvent; // Ensure event is raised even if already loaded _ = sv.Scene.RetryLoadAsync(); @@ -240,10 +251,13 @@ private void Doc_Loaded(object? sender, EventArgs e) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - var listener = new WeakEventListener(this, bmCollection); - listener.OnEventAction = static (instance, source, eventArgs) => instance.HandleGeoViewBookmarksCollectionChanged(source, eventArgs); - listener.OnDetachAction = static (instance, source, weakEventListener) => source.CollectionChanged -= weakEventListener.OnEvent; - bmCollection.CollectionChanged += listener.OnEvent; + _geoViewBookmarksListener?.Detach(); + _geoViewBookmarksListener = new WeakEventListener(this, bmCollection) + { + OnEventAction = static (instance, source, eventArgs) => instance.HandleGeoViewBookmarksCollectionChanged(source, eventArgs), + OnDetachAction = static (instance, source, weakEventListener) => source.CollectionChanged -= weakEventListener.OnEvent + }; + bmCollection.CollectionChanged += _geoViewBookmarksListener.OnEvent; } private void HandleGeoViewBookmarksCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)