diff --git a/README.md b/README.md index 57f101aa1..211200980 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ There are two ways to add Toolkit to your project: > See [List of controls](https://esri.github.io/arcgis-toolkit-dotnet/controls.html) for a full list of controls with screenshots - **[ARSceneView](https://esri.github.io/arcgis-toolkit-dotnet/ar.html)**: Part of the AR Toolkit, enables integration of GIS content and ARKit/ARCore. -- **[BasemapGallery](https://esri.github.io/arcgis-toolkit-dotnet/basemap-gallery.htm)**: Shows basemaps, either from a Portal or a custom collection; applies the selected basemap to the connected GeoModel. +- **[BasemapGallery](https://esri.github.io/arcgis-toolkit-dotnet/basemap-gallery.html)**: Shows basemaps, either from a Portal or a custom collection; applies the selected basemap to the connected GeoModel. - **[Bookmarks](https://esri.github.io/arcgis-toolkit-dotnet/bookmarks-view.html)**: Shows bookmarks, from a map, scene, or a list; navigates the associated MapView/SceneView when a bookmark is selected. - **Compass**: Shows a compass direction when the map is rotated. Auto-hides when the map points north up. - **FeatureDataField**: Displays and optionally allows editing of a single field attribute of a feature. diff --git a/src/Toolkit.Forms/BasemapGallery/BasemapGallery.cs b/src/Toolkit.Forms/BasemapGallery/BasemapGallery.cs index 8fdb51d2b..311eec4bc 100644 --- a/src/Toolkit.Forms/BasemapGallery/BasemapGallery.cs +++ b/src/Toolkit.Forms/BasemapGallery/BasemapGallery.cs @@ -15,14 +15,11 @@ // ******************************************************************************/ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using Esri.ArcGISRuntime.Mapping; using Esri.ArcGISRuntime.Portal; using Esri.ArcGISRuntime.Toolkit.UI; -using Esri.ArcGISRuntime.Toolkit.UI.Controls; using Xamarin.Forms; namespace Esri.ArcGISRuntime.Toolkit.Xamarin.Forms @@ -34,23 +31,46 @@ namespace Esri.ArcGISRuntime.Toolkit.Xamarin.Forms /// If connected to a GeoView, changing the basemap selection will change the connected Map or Scene's basemap. /// Only basemaps whose spatial reference matches the map or scene's spatial reference can be selected for display. /// - public partial class BasemapGallery : IBasemapGallery + public partial class BasemapGallery { private CollectionView? _listView; - private BasemapGalleryController _controller; + private readonly BasemapGalleryController _controller; /// /// Initializes a new instance of the class. /// public BasemapGallery() { - _controller = new BasemapGalleryController(this); + _controller = new BasemapGalleryController(); + _controller.PropertyChanged += HandleControllerPropertyChanged; ListItemTemplate = DefaultListDataTemplate; GridItemTemplate = DefaultGridDataTemplate; ControlTemplate = DefaultControlTemplate; _ = _controller.LoadFromDefaultPortal(); } + private void HandleControllerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(BasemapGalleryController.AvailableBasemaps): + AvailableBasemaps = _controller.AvailableBasemaps; + break; + case nameof(BasemapGalleryController.IsLoading): + _loadingScrim?.SetValue(View.IsVisibleProperty, _controller.IsLoading); + break; + case nameof(BasemapGalleryController.SelectedBasemap): + SelectedBasemap = _controller.SelectedBasemap; + _listView?.SetValue(CollectionView.SelectedItemProperty, _controller.SelectedBasemap); + if (_controller.SelectedBasemap != null) + { + BasemapSelected?.Invoke(this, _controller.SelectedBasemap); + } + + break; + } + } + private CollectionView? ListView { get => _listView; @@ -67,7 +87,6 @@ private CollectionView? ListView if (_listView != null) { - _controller.HandleListViewChanged(); _listView.SelectionChanged += ListViewSelectionChanged; HandleTemplateChange(Width); } @@ -79,7 +98,7 @@ private static void SelectedBasemapChanged(BindableObject sender, object oldValu { if (sender is BasemapGallery gallery) { - gallery._controller.HandleSelectedBasemapChanged(); + gallery._controller.SelectedBasemap = newValue as BasemapGalleryItem; } } @@ -90,25 +109,10 @@ private static void GeoModelChanged(BindableObject sender, object oldValue, obje { if (sender is BasemapGallery gallery) { - if (oldValue is GeoModel oldModel) - { - oldModel.PropertyChanged -= gallery.GeoModelPropertyChanged; - } - - gallery._controller.HandleGeoModelChanged(); - - if (newValue is GeoModel newModel) - { - newModel.PropertyChanged += gallery.GeoModelPropertyChanged; - } + gallery._controller.GeoModel = newValue as GeoModel; } } - private void GeoModelPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - _controller.HandleGeoModelPropertyChanged(e.PropertyName); - } - private void ListViewSelectionChanged(object sender, SelectionChangedEventArgs e) { if (ListView == null) @@ -118,13 +122,13 @@ private void ListViewSelectionChanged(object sender, SelectionChangedEventArgs e if (e.CurrentSelection.Count == 0) { - _controller.HandleListViewSelectionChanged(null); + SelectedBasemap = null; } else if (e.CurrentSelection.FirstOrDefault() is BasemapGalleryItem selectedItem) { if (selectedItem.IsValid) { - _controller.HandleListViewSelectionChanged(e.CurrentSelection.FirstOrDefault() as BasemapGalleryItem); + SelectedBasemap = selectedItem; } } } @@ -136,7 +140,7 @@ private static void PortalChanged(BindableObject sender, object oldValue, object { if (sender is BasemapGallery gallery) { - _ = gallery._controller.HandlePortalChanged(); + gallery._controller.Portal = newValue as ArcGISPortal; } } @@ -144,25 +148,14 @@ private static void AvailableBasemapsChanged(BindableObject sender, object oldVa { if (sender is BasemapGallery gallery) { - if (oldValue is ObservableCollection oldAvailableBasemaps) + gallery.ListView?.SetValue(CollectionView.ItemsSourceProperty, newValue); + if (newValue != gallery._controller.AvailableBasemaps) { - oldAvailableBasemaps.CollectionChanged -= gallery.AvailableBasemapsCollectionChanged; - } - - gallery._controller.HandleAvailableBasemapsChanged(); - - if (newValue is ObservableCollection newAvailableBasemaps) - { - newAvailableBasemaps.CollectionChanged += gallery.AvailableBasemapsCollectionChanged; + gallery._controller.AvailableBasemaps = newValue as IList; } } } - private void AvailableBasemapsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - _controller.HandleAvailableBasemapsCollectionChanged(e); - } - /// /// Event raised when a basemap is selected. /// @@ -175,7 +168,7 @@ private void AvailableBasemapsCollectionChanged(object sender, NotifyCollectionC /// public ArcGISPortal? Portal { - get => (ArcGISPortal)GetValue(PortalProperty); + get => GetValue(PortalProperty) as ArcGISPortal; set => SetValue(PortalProperty, value); } @@ -239,40 +232,5 @@ public BasemapGalleryItem? SelectedBasemap #endregion Bindable Properties - #region Controller Callbacks - - void IBasemapGallery.SetListViewSource(IList? newSource) - { - if (ListView != null) - { - ListView.ItemsSource = newSource; - } - } - - void IBasemapGallery.SetListViewSelection(BasemapGalleryItem? item) - { - if (ListView != null) - { - ListView.SelectedItem = item; - } - } - - void IBasemapGallery.NotifyBasemapSelected(BasemapGalleryItem item) - { - BasemapSelected?.Invoke(this, item); - } - - void IBasemapGallery.SetIsLoading(bool isLoading) - { - if (isLoading && _loadingScrim != null) - { - _loadingScrim.IsVisible = true; - } - else if (_loadingScrim != null) - { - _loadingScrim.IsVisible = false; - } - } - #endregion Controller Callbacks } } diff --git a/src/Toolkit.Forms/BasemapGallery/ByteArrayToImageSourceConverter.cs b/src/Toolkit.Forms/BasemapGallery/ByteArrayToImageSourceConverter.cs index 876e96c0f..a3a9139a6 100644 --- a/src/Toolkit.Forms/BasemapGallery/ByteArrayToImageSourceConverter.cs +++ b/src/Toolkit.Forms/BasemapGallery/ByteArrayToImageSourceConverter.cs @@ -26,7 +26,7 @@ internal class ByteArrayToImageSourceConverter : IValueConverter /// /// Converts a byte array to an image source for display in Xamarin.Forms. /// - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is byte[] rawBuffer) { diff --git a/src/Toolkit/Toolkit/Esri.ArcGISRuntime.Toolkit.csproj b/src/Toolkit/Toolkit/Esri.ArcGISRuntime.Toolkit.csproj index 96ebc6b83..af2569af8 100644 --- a/src/Toolkit/Toolkit/Esri.ArcGISRuntime.Toolkit.csproj +++ b/src/Toolkit/Toolkit/Esri.ArcGISRuntime.Toolkit.csproj @@ -66,7 +66,6 @@ - diff --git a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGallery.Windows.cs b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGallery.Windows.cs index eac996487..6882dcead 100644 --- a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGallery.Windows.cs +++ b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGallery.Windows.cs @@ -18,16 +18,17 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.ComponentModel; using Esri.ArcGISRuntime.Mapping; using Esri.ArcGISRuntime.Portal; #if NETFX_CORE using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; #else using System.Windows; using System.Windows.Controls; +using System.Windows.Data; #endif namespace Esri.ArcGISRuntime.Toolkit.UI.Controls @@ -39,7 +40,7 @@ namespace Esri.ArcGISRuntime.Toolkit.UI.Controls /// If connected to a GeoView, changing the basemap selection will change the connected Map or Scene's basemap. /// Only basemaps whose spatial reference matches the map or scene's spatial reference can be selected for display. /// - public partial class BasemapGallery : Control, IBasemapGallery + public partial class BasemapGallery : Control { private readonly BasemapGalleryController _controller; @@ -48,13 +49,36 @@ public partial class BasemapGallery : Control, IBasemapGallery /// public BasemapGallery() { - _controller = new BasemapGalleryController(this); + _controller = new BasemapGalleryController(); DefaultStyleKey = typeof(BasemapGallery); SizeChanged += BasemapGallerySizeChanged; AvailableBasemaps = new ObservableCollection(); + _controller.PropertyChanged += HandleControllerPropertyChanged; _ = _controller.LoadFromDefaultPortal(); } + private void HandleControllerPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(BasemapGalleryController.AvailableBasemaps): + AvailableBasemaps = _controller.AvailableBasemaps; + break; + case nameof(BasemapGalleryController.IsLoading): + _loadingScrim?.SetValue(FrameworkElement.VisibilityProperty, _controller.IsLoading ? Visibility.Visible : Visibility.Collapsed); + break; + case nameof(BasemapGalleryController.SelectedBasemap): + ListView?.SetValue(ListView.SelectedItemProperty, _controller.SelectedBasemap); + SelectedBasemap = _controller.SelectedBasemap; + if (_controller.SelectedBasemap != null) + { + BasemapSelected?.Invoke(this, _controller.SelectedBasemap); + } + + break; + } + } + private ListView? ListView { get => _listView; @@ -71,7 +95,6 @@ private ListView? ListView if (_listView != null) { - _controller.HandleListViewChanged(); _listView.SelectionChanged += ListViewSelectionChanged; } } @@ -82,7 +105,7 @@ private static void SelectedBasemapChanged(DependencyObject d, DependencyPropert { if (d is BasemapGallery gallery) { - gallery._controller.HandleSelectedBasemapChanged(); + gallery._controller.SelectedBasemap = e.NewValue as BasemapGalleryItem; } } @@ -90,25 +113,10 @@ private static void GeoModelChanged(DependencyObject d, DependencyPropertyChange { if (d is BasemapGallery gallery) { - if (e.OldValue is GeoModel oldModel) - { - oldModel.PropertyChanged -= gallery.GeoModelPropertyChanged; - } - - gallery._controller.HandleGeoModelChanged(); - - if (e.NewValue is GeoModel newModel) - { - newModel.PropertyChanged += gallery.GeoModelPropertyChanged; - } + gallery._controller.GeoModel = e.NewValue as GeoModel; } } - private void GeoModelPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - _controller.HandleGeoModelPropertyChanged(e.PropertyName ?? string.Empty); - } - private void ListViewSelectionChanged(object? sender, SelectionChangedEventArgs e) { if (ListView == null) @@ -116,14 +124,14 @@ private void ListViewSelectionChanged(object? sender, SelectionChangedEventArgs return; } - _controller.HandleListViewSelectionChanged(ListView.SelectedItem as BasemapGalleryItem); + SelectedBasemap = ListView.SelectedItem as BasemapGalleryItem; } private static void PortalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is BasemapGallery gallery) { - _ = gallery._controller.HandlePortalChanged(); + gallery._controller.Portal = gallery.Portal; } } @@ -131,25 +139,14 @@ private static void AvailableBasemapsChanged(DependencyObject d, DependencyPrope { if (d is BasemapGallery gallery) { - if (e.OldValue is ObservableCollection oldAvailableBasemaps) + gallery.ListView?.SetBinding(ListView.ItemsSourceProperty, new Binding { Source = gallery._controller.AvailableBasemaps, Mode = BindingMode.OneWay }); + if (e.NewValue != gallery._controller.AvailableBasemaps) { - oldAvailableBasemaps.CollectionChanged -= gallery.AvailableBasemapsCollectionChanged; - } - - gallery._controller.HandleAvailableBasemapsChanged(); - - if (e.NewValue is ObservableCollection newAvailableBasemaps) - { - newAvailableBasemaps.CollectionChanged += gallery.AvailableBasemapsCollectionChanged; + gallery._controller.AvailableBasemaps = e.NewValue as IList; } } } - private void AvailableBasemapsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - _controller.HandleAvailableBasemapsCollectionChanged(e); - } - #region Convenience Properties /// @@ -227,41 +224,6 @@ public BasemapGalleryItem? SelectedBasemap /// Event raised when a basemap is selected. /// public event EventHandler? BasemapSelected; - - #region Controller Callbacks - void IBasemapGallery.SetListViewSource(IList? newSource) - { - if (ListView != null) - { - ListView.ItemsSource = newSource; - } - } - - void IBasemapGallery.SetListViewSelection(BasemapGalleryItem? item) - { - if (ListView != null) - { - ListView.SelectedItem = item; - } - } - - void IBasemapGallery.NotifyBasemapSelected(BasemapGalleryItem item) - { - BasemapSelected?.Invoke(this, item); - } - - void IBasemapGallery.SetIsLoading(bool isLoading) - { - if (isLoading && _loadingScrim != null) - { - _loadingScrim.Visibility = Visibility.Visible; - } - else if (_loadingScrim != null) - { - _loadingScrim.Visibility = Visibility.Collapsed; - } - } - #endregion Controller Callbacks } } #endif diff --git a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryController.cs b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryController.cs index 83bfeeaa3..cb9188bb3 100644 --- a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryController.cs +++ b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryController.cs @@ -17,35 +17,124 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.ComponentModel; using System.Linq; using System.Threading.Tasks; using Esri.ArcGISRuntime.Mapping; using Esri.ArcGISRuntime.Portal; -using Esri.ArcGISRuntime.Toolkit.UI.Controls; + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Esri.ArcGISRuntime.Toolkit.Xamarin.Forms")] namespace Esri.ArcGISRuntime.Toolkit.UI { - internal class BasemapGalleryController + internal class BasemapGalleryController : INotifyPropertyChanged { - private IBasemapGallery _gallery; + private ArcGISPortal? _portal; private bool _ignoreEventsFlag; + private IList? _availableBasemaps; + private GeoModel? _geoModel; + private BasemapGalleryItem? _selectedBasemap; + private bool _isLoading; + + public bool IsLoading + { + get => _isLoading; + set + { + if (value != _isLoading) + { + _isLoading = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLoading))); + } + } + } + + public IList? AvailableBasemaps + { + get => _availableBasemaps; + set + { + if (value != _availableBasemaps) + { + if (_availableBasemaps is INotifyCollectionChanged oldIncc) + { + oldIncc.CollectionChanged -= HandleAvailableBasemapsCollectionChanged; + } + + _availableBasemaps = value; + + if (_availableBasemaps is INotifyCollectionChanged newIncc) + { + newIncc.CollectionChanged += HandleAvailableBasemapsCollectionChanged; + } + + HandleAvailableBasemapsChanged(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AvailableBasemaps))); + } + } + } + + public BasemapGalleryItem? SelectedBasemap + { + get => _selectedBasemap; + set + { + if (_selectedBasemap != value) + { + _selectedBasemap = value; + HandleSelectedBasemapChanged(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedBasemap))); + } + } + } - public BasemapGalleryController(IBasemapGallery gallery) + public GeoModel? GeoModel { - _gallery = gallery; + get => _geoModel; + set + { + if (value != _geoModel) + { + if (_geoModel is INotifyPropertyChanged oldGeoModel) + { + oldGeoModel.PropertyChanged -= HandleGeoModelPropertyChanged; + } + + _geoModel = value; + + if (_geoModel is INotifyPropertyChanged newGeoModel) + { + newGeoModel.PropertyChanged += HandleGeoModelPropertyChanged; + } + + HandleGeoModelChanged(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(GeoModel))); + } + } } - public void HandleAvailableBasemapsChanged() + public ArcGISPortal? Portal + { + get => _portal; + set + { + if (value != _portal) + { + _portal = value; + _ = HandlePortalChanged(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Portal))); + } + } + } + + private void HandleAvailableBasemapsChanged() { _ignoreEventsFlag = true; try { // Update validity - _gallery.AvailableBasemaps?.ToList()?.ForEach(bmgi => bmgi.NotifySpatialReferenceChanged(_gallery.GeoModel)); - - // Show new items in UI - _gallery.SetListViewSource(_gallery.AvailableBasemaps); + AvailableBasemaps?.ToList()?.ForEach(bmgi => bmgi.NotifySpatialReferenceChanged(GeoModel)); // Update selection. _ = UpdateSelectionForGeoModelBasemap(); @@ -56,7 +145,7 @@ public void HandleAvailableBasemapsChanged() } } - public void HandleAvailableBasemapsCollectionChanged(NotifyCollectionChangedEventArgs e) + private void HandleAvailableBasemapsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { @@ -64,7 +153,7 @@ public void HandleAvailableBasemapsCollectionChanged(NotifyCollectionChangedEven case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Reset: - e.NewItems?.OfType().ToList().ForEach(bmgi => bmgi.NotifySpatialReferenceChanged(_gallery.GeoModel)); + e.NewItems?.OfType().ToList().ForEach(bmgi => bmgi.NotifySpatialReferenceChanged(GeoModel)); _ = UpdateSelectionForGeoModelBasemap(); break; case NotifyCollectionChangedAction.Remove: @@ -73,88 +162,53 @@ public void HandleAvailableBasemapsCollectionChanged(NotifyCollectionChangedEven } } - public void HandleGeoModelChanged() + private void HandleGeoModelChanged() { - _gallery.AvailableBasemaps?.ToList().ForEach(item => item.NotifySpatialReferenceChanged(_gallery.GeoModel)); + AvailableBasemaps?.ToList().ForEach(item => item.NotifySpatialReferenceChanged(GeoModel)); _ = UpdateSelectionForGeoModelBasemap(); } - public void HandleGeoModelPropertyChanged(string propertyName) + private void HandleGeoModelPropertyChanged(object? sender, PropertyChangedEventArgs e) { - if (propertyName == nameof(GeoModel.Basemap) && !_ignoreEventsFlag) + if (e.PropertyName == nameof(GeoModel.Basemap) && !_ignoreEventsFlag) { _ = UpdateSelectionForGeoModelBasemap(); } - else if (propertyName == nameof(GeoModel.SpatialReference)) + else if (e.PropertyName == nameof(GeoModel.SpatialReference)) { - _gallery.AvailableBasemaps?.ToList().ForEach(item => item.NotifySpatialReferenceChanged(_gallery.GeoModel)); + AvailableBasemaps?.ToList().ForEach(item => item.NotifySpatialReferenceChanged(GeoModel)); } } - public void HandleListViewChanged() - { - _gallery.SetListViewSource(_gallery.AvailableBasemaps); - _gallery.SetListViewSelection(_gallery.SelectedBasemap); - } - - public void HandleListViewSelectionChanged(BasemapGalleryItem? newSelection) + private async Task HandlePortalChanged() { - if (_ignoreEventsFlag) - { - return; - } - + IsLoading = true; try { - _ignoreEventsFlag = true; - _gallery.SelectedBasemap = newSelection; - } - catch (Exception) - { - // Ignore - } - finally - { - _ignoreEventsFlag = false; - } - } - - public async Task HandlePortalChanged() - { - _gallery.SetIsLoading(true); - try - { - if (_gallery.Portal is ArcGISPortal portal) + if (Portal is ArcGISPortal portal) { if (await PopulateBasemapsForPortal(portal) is List portalItems) { - _gallery.AvailableBasemaps = new ObservableCollection(portalItems); + AvailableBasemaps = new ObservableCollection(portalItems); } } } finally { - _gallery.SetIsLoading(false); + IsLoading = false; } } - public void HandleSelectedBasemapChanged() + private void HandleSelectedBasemapChanged() { try { // Stop listening to list events _ignoreEventsFlag = true; - _gallery.SetListViewSelection(_gallery.SelectedBasemap); - - if (_gallery.GeoModel != null && (!_gallery.SelectedBasemap?.EqualsBasemap(_gallery.GeoModel.Basemap) ?? true)) + if (GeoModel != null && (!SelectedBasemap?.EqualsBasemap(GeoModel.Basemap) ?? true)) { - _gallery.GeoModel.Basemap = _gallery.SelectedBasemap?.Basemap?.Clone(); - } - - if (_gallery.SelectedBasemap is BasemapGalleryItem selectedItem) - { - _gallery.NotifyBasemapSelected(selectedItem); + GeoModel.Basemap = SelectedBasemap?.Basemap?.Clone(); } } catch (Exception) @@ -170,41 +224,37 @@ public void HandleSelectedBasemapChanged() public async Task LoadFromDefaultPortal() { - _gallery.SetIsLoading(true); + IsLoading = true; try { - var portalItems = await PopulateFromDefaultList(); - if (portalItems != null) - { - _gallery.AvailableBasemaps = new ObservableCollection(portalItems); - } + AvailableBasemaps = await PopulateFromDefaultList(); } finally { - _gallery.SetIsLoading(false); + IsLoading = false; } } - public async Task UpdateSelectionForGeoModelBasemap() + private async Task UpdateSelectionForGeoModelBasemap() { - if (_gallery.GeoModel?.Basemap is Basemap inputBasemap) + if (GeoModel?.Basemap is Basemap inputBasemap) { if (await BasemapIsActuallyNotABasemap(inputBasemap)) { - _gallery.SelectedBasemap = null; + SelectedBasemap = null; } - else if (_gallery.AvailableBasemaps?.FirstOrDefault(bmgi => bmgi.EqualsBasemap(inputBasemap)) is BasemapGalleryItem selectedItem) + else if (AvailableBasemaps?.FirstOrDefault(bmgi => bmgi.EqualsBasemap(inputBasemap)) is BasemapGalleryItem selectedItem) { - _gallery.SelectedBasemap = selectedItem; + SelectedBasemap = selectedItem; } else { - _gallery.SelectedBasemap = null; + SelectedBasemap = null; } } else { - _gallery.SelectedBasemap = null; + SelectedBasemap = null; } } @@ -222,7 +272,7 @@ private static async Task BasemapIsActuallyNotABasemap(Basemap input) return false; } - private static async Task?> PopulateBasemapsForPortal(ArcGISPortal? portal) + private static async Task?> PopulateBasemapsForPortal(ArcGISPortal? portal) { if (portal == null) { @@ -241,16 +291,16 @@ private static async Task BasemapIsActuallyNotABasemap(Basemap input) var basemaps = await getBasemapsTask; - List listOfBasemaps = new List(); + IList listOfBasemaps = new List(); foreach (var item in basemaps) { listOfBasemaps.Add(new BasemapGalleryItem(item)); } - #if !WINDOWS_UWP && !NETCOREAPP && !NETCOREAPP3_1 +#if !WINDOWS_UWP && !NETCOREAPP && !NETCOREAPP3_1 await Task.WhenAll(listOfBasemaps.Select(gi => gi.LoadAsync())); - #else +#else foreach (var item in listOfBasemaps) { try @@ -261,18 +311,18 @@ private static async Task BasemapIsActuallyNotABasemap(Basemap input) { } } - #endif +#endif return listOfBasemaps; } - private static async Task> PopulateFromDefaultList() + private static async Task> PopulateFromDefaultList() { ArcGISPortal defaultPortal = await ArcGISPortal.CreateAsync(); var results = await defaultPortal.GetDeveloperBasemapsAsync(); - List listOfBasemaps = new List(); + var listOfBasemaps = new List(); foreach (var basemap in results) { @@ -293,7 +343,9 @@ private static async Task> PopulateFromDefaultList() } } #endif - return listOfBasemaps; + return new ObservableCollection(listOfBasemaps); } + + public event PropertyChangedEventHandler? PropertyChanged; } } diff --git a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryItem.cs b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryItem.cs index cb647b936..e9b33535f 100644 --- a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryItem.cs +++ b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/BasemapGalleryItem.cs @@ -32,7 +32,9 @@ namespace Esri.ArcGISRuntime.Toolkit.UI /// public class BasemapGalleryItem : INotifyPropertyChanged, IEquatable { +#pragma warning disable SA1011 // Closing square brackets should be spaced correctly private byte[]? _thumbnailData; +#pragma warning restore SA1011 // Closing square brackets should be spaced correctly private RuntimeImage? _thumbnailOverride; private string? _tooltipOverride; private string? _nameOverride; @@ -76,7 +78,7 @@ internal async Task LoadAsync() { if (Basemap != null && Basemap.LoadStatus != LoadStatus.Loaded) { - await Basemap.RetryLoadAsync(); + await Basemap.LoadAsync(); } PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name))); @@ -111,20 +113,17 @@ private async Task LoadImage() IsLoading = true; try { - if (Thumbnail != null && Thumbnail.LoadStatus != LoadStatus.Loaded) - { - await Thumbnail.RetryLoadAsync(); - } + await (Thumbnail?.LoadAsync() ?? Task.CompletedTask); - if (Thumbnail != null && Thumbnail.LoadStatus == LoadStatus.Loaded) + if (Thumbnail?.LoadStatus == LoadStatus.Loaded) { var stream = await Thumbnail.GetEncodedBufferAsync(); var buffer = new byte[stream.Length]; await stream.ReadAsync(buffer, 0, (int)stream.Length); ThumbnailData = buffer; - #if WINDOWS_UWP +#if WINDOWS_UWP ThumbnailBitmap = await Thumbnail.ToImageSourceAsync(); - #endif +#endif } } catch (Exception) @@ -182,7 +181,9 @@ private set /// /// Gets thumbnail as a byte array. /// +#pragma warning disable SA1011 // Closing square brackets should be spaced correctly public byte[]? ThumbnailData +#pragma warning restore SA1011 // Closing square brackets should be spaced correctly { get => _thumbnailData; private set @@ -195,7 +196,7 @@ private set } } - #if WINDOWS_UWP +#if WINDOWS_UWP private ImageSource? _thumbnailBitmap; /// diff --git a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/IBasemapGallery.cs b/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/IBasemapGallery.cs deleted file mode 100644 index bdc945c42..000000000 --- a/src/Toolkit/Toolkit/UI/Controls/BasemapGallery/IBasemapGallery.cs +++ /dev/null @@ -1,46 +0,0 @@ -// /******************************************************************************* -// * Copyright 2012-2018 Esri -// * -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// ******************************************************************************/ - -using System.Collections.Generic; -using Esri.ArcGISRuntime.Mapping; -using Esri.ArcGISRuntime.Portal; - -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Esri.ArcGISRuntime.Toolkit.Xamarin.Forms")] - -namespace Esri.ArcGISRuntime.Toolkit.UI.Controls -{ - /// - /// Internal interface enables code sharing for with Forms- and Windows-specific BasemapGallery implementations. - /// - internal interface IBasemapGallery - { - public GeoModel? GeoModel { get; set; } - - public BasemapGalleryItem? SelectedBasemap { get; set; } - - public IList? AvailableBasemaps { get; set; } - - public ArcGISPortal? Portal { get; set; } - - internal void SetListViewSource(IList? newSource); - - internal void SetListViewSelection(BasemapGalleryItem? item); - - internal void NotifyBasemapSelected(BasemapGalleryItem item); - - internal void SetIsLoading(bool isLoading); - } -} diff --git a/src/Toolkit/Toolkit/VisualStudioToolsManifest.xml b/src/Toolkit/Toolkit/VisualStudioToolsManifest.xml index 7e4f8d042..7e1e88a9f 100644 --- a/src/Toolkit/Toolkit/VisualStudioToolsManifest.xml +++ b/src/Toolkit/Toolkit/VisualStudioToolsManifest.xml @@ -2,6 +2,7 @@ +