Skip to content
Merged
19 changes: 13 additions & 6 deletions src/Toolkit/Toolkit.Maui/SearchView/SearchView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public partial class SearchView : TemplatedView, INotifyPropertyChanged

private bool _sourceSelectToggled;

private bool _loadedHandled;

/// <summary>
/// Initializes a new instance of the <see cref="SearchView"/> class.
/// </summary>
Expand Down Expand Up @@ -81,6 +83,16 @@ public SearchView()
ClearCommand = new DelegateCommand(HandleClearSearchCommand);
SearchCommand = new DelegateCommand(HandleSearchCommand);
RepeatSearchHereCommand = new DelegateCommand(HandleRepeatSearchHereCommand);
Loaded += SearchView_Loaded;
}

private void SearchView_Loaded(object? sender, EventArgs e)
{
if (GeoView != null)
{
HandleViewpointChanged();
}
_ = ConfigureForCurrentConfiguration();
}

private void InitializeLocalizedStrings()
Expand Down Expand Up @@ -450,8 +462,6 @@ private static void OnGeoViewPropertyChanged(BindableObject sender, object? oldV
newGeoView.ViewpointChanged += sendingView.GeoView_ViewpointChanged;
newGeoView.GraphicsOverlays?.Add(sendingView._resultOverlay);
}

_ = sendingView.ConfigureForCurrentConfiguration();
}
}

Expand Down Expand Up @@ -531,7 +541,6 @@ private void HandleMapChange(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Mapping.Map) || e.PropertyName == nameof(Scene))
{
_ = ConfigureForCurrentConfiguration();
return;
}

Expand All @@ -545,8 +554,6 @@ private void HandleMapChange(object? sender, PropertyChangedEventArgs e)
{
_lastUsedGeomodel = scene;
}

_ = ConfigureForCurrentConfiguration();
}
}

Expand Down Expand Up @@ -620,7 +627,7 @@ private void SearchViewModel_PropertyChanged(object? sender, PropertyChangedEven
/// </summary>
private void HandleViewpointChanged()
{
if (SearchViewModel == null)
if (!IsLoaded || SearchViewModel == null)
{
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Toolkit/Toolkit.UI.Controls/SearchView/SearchView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ public string? RepeatSearchButtonText
/// Identifies the <see cref="EnableDefaultWorldGeocoder"/> dependency property.
/// </summary>
public static readonly DependencyProperty EnableDefaultWorldGeocoderProperty =
DependencyProperty.Register(nameof(EnableDefaultWorldGeocoder), typeof(bool), typeof(SearchView), new PropertyMetadata(false, OnEnableDefualtWorldGeocoderPropertyChanged));
DependencyProperty.Register(nameof(EnableDefaultWorldGeocoder), typeof(bool), typeof(SearchView), new PropertyMetadata(true, OnEnableDefualtWorldGeocoderPropertyChanged));

/// <summary>
/// Identifies the <see cref="EnableRepeatSearchHereButton"/> dependency proeprty.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,5 @@
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Width" Value="256" />
<Setter Property="Margin" Value="4" />
<Setter Property="EnableDefaultWorldGeocoder" Value="True" />
</Style>
</ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,5 @@
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Width" Value="256" />
<Setter Property="Margin" Value="4" />
<Setter Property="EnableDefaultWorldGeocoder" Value="True" />
</Style>
</ResourceDictionary>
74 changes: 58 additions & 16 deletions src/Toolkit/Toolkit/UI/Controls/SearchView/LocatorSearchSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
Expand All @@ -36,7 +37,7 @@ namespace Esri.ArcGISRuntime.Toolkit.UI.Controls
/// <summary>
/// Basic search source implementation for generic locators.
/// </summary>
public class LocatorSearchSource : ISearchSource
public class LocatorSearchSource : ISearchSource, INotifyPropertyChanged
{
internal const string WorldGeocoderUriString = "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer";

Expand All @@ -62,17 +63,41 @@ public static async Task<LocatorSearchSource> CreateDefaultSourceAsync(Cancellat
return new WorldGeocoderSearchSource(_worldGeocoderTask, null);
}

private readonly Task _loadTask;

/// <inheritdoc/>
public event PropertyChangedEventHandler? PropertyChanged;

/// <summary>
/// Raises the <see cref="PropertyChanged"/> event for the specified property.
/// </summary>
/// <param name="propertyName">The name of the property that changed.</param>
protected virtual void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

private readonly Lazy<Task> _loadTask;
/// <summary>
/// Gets the task used to perform initial locator setup.
/// </summary>
protected Task LoadTask => _loadTask;
protected Lazy<Task> LoadTask => _loadTask;

private string _displayName = string.Empty;
private bool _displayNameSetExternally = false;

/// <summary>
/// Gets or sets the name of the locator. Defaults to the locator's name, or "locator" if not set.
/// </summary>
public string DisplayName { get; set; } = "Locator";
public string DisplayName
{
get => _displayName;
set
{
if (_displayName != value)
{
_displayName = value;
_displayNameSetExternally = true;
OnPropertyChanged(nameof(DisplayName));
}
}
}

/// <summary>
/// Gets or sets the maximum number of results to return for a search. Default is 6.
Expand Down Expand Up @@ -146,12 +171,36 @@ public LocatorSearchSource(LocatorTask locator)
{
Locator = locator;

_loadTask = EnsureLoaded();
RefreshDisplayName();

_loadTask = new Lazy<Task>(EnsureLoaded);
}

private void RefreshDisplayName()
{
if (_displayNameSetExternally)
return;

if (Locator?.LocatorInfo is LocatorInfo info)
{
// Locators from online services have descriptions but not names.
if (!string.IsNullOrWhiteSpace(info.Name) && info.Name != Locator.Uri?.ToString())
_displayName = info.Name;
else if (!string.IsNullOrWhiteSpace(info.Description))
_displayName = info.Description;
else
_displayName = string.Empty;

OnPropertyChanged(nameof(DisplayName));
}

GeocodeParameters.ResultAttributeNames.Add("*");
}

private async Task EnsureLoaded()
{
await Locator.LoadAsync();
RefreshDisplayName();
#if MAUI
Stream? resourceStream = Assembly.GetAssembly(typeof(LocatorSearchSource))?.GetManifestResourceStream(
"Esri.ArcGISRuntime.Toolkit.Maui.Assets.pin-red.png");
Expand All @@ -169,13 +218,6 @@ private async Task EnsureLoaded()
pinSymbol.OffsetY = 16.5;
DefaultSymbol = pinSymbol;
}

if (DisplayName != Locator?.LocatorInfo?.Name && !string.IsNullOrWhiteSpace(Locator?.LocatorInfo?.Name))
{
DisplayName = Locator?.LocatorInfo?.Name ?? "Locator";
}

GeocodeParameters.ResultAttributeNames.Add("*");
}

/// <summary>
Expand All @@ -197,7 +239,7 @@ public virtual void NotifyDeselected(SearchResult? result)
/// <inheritdoc/>
public virtual async Task<IList<SearchSuggestion>> SuggestAsync(string queryString, CancellationToken cancellationToken = default)
{
await _loadTask;
await LoadTask.Value;

cancellationToken.ThrowIfCancellationRequested();

Expand All @@ -214,7 +256,7 @@ public virtual async Task<IList<SearchSuggestion>> SuggestAsync(string queryStri
/// <inheritdoc/>
public virtual async Task<IList<SearchResult>> SearchAsync(SearchSuggestion suggestion, CancellationToken cancellationToken = default)
{
await _loadTask;
await LoadTask.Value;

cancellationToken.ThrowIfCancellationRequested();

Expand All @@ -228,7 +270,7 @@ public virtual async Task<IList<SearchResult>> SearchAsync(SearchSuggestion sugg
/// <inheritdoc/>
public virtual async Task<IList<SearchResult>> SearchAsync(string queryString, CancellationToken cancellationToken = default)
{
await _loadTask;
await LoadTask.Value;

cancellationToken.ThrowIfCancellationRequested();

Expand All @@ -246,7 +288,7 @@ public virtual async Task<IList<SearchResult>> SearchAsync(string queryString, C
/// <inheritdoc />
public virtual async Task<IList<SearchResult>> RepeatSearchAsync(string queryString, Envelope queryExtent, CancellationToken cancellationToken = default)
{
await _loadTask;
await LoadTask.Value;

cancellationToken.ThrowIfCancellationRequested();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ internal class WorldGeocoderSearchSource : LocatorSearchSource
// Attribute used to identify the type of result coming from the locaotr.
private const string LocatorIconAttributeKey = "Type";

private readonly Task _additionalLoadTask;

/// <summary>
/// Gets or sets the minimum number of results to attempt to return.
/// If there are too few results, the search is repeated with loosened parameters until enough results are accumulated.
Expand Down Expand Up @@ -87,27 +85,11 @@ public WorldGeocoderSearchSource(LocatorTask locator, SymbolStyle? style)
{
ResultSymbolStyle = style;
}

_additionalLoadTask = EnsureLoaded();
InitializeLocatorAttributes();
}

private async Task EnsureLoaded()
private void InitializeLocatorAttributes()
{
await LoadTask;

if (Locator.LocatorInfo is LocatorInfo info)
{
// Locators from online services have descriptions but not names.
if (!string.IsNullOrWhiteSpace(info.Name) && info.Name != Locator.Uri?.ToString())
{
DisplayName = info.Name;
}
else if (!string.IsNullOrWhiteSpace(info.Description))
{
DisplayName = info.Description;
}
}

// Add attributes expected from the World Geocoder Service if present, otherwise default to all attributes.
if (Locator.Uri?.ToString() == WorldGeocoderUriString &&
(Locator.LocatorInfo?.ResultAttributes?.Any() == true))
Expand Down Expand Up @@ -140,7 +122,7 @@ private IList<SearchSuggestion> SuggestionToSearchSuggestion(IReadOnlyList<Sugge
/// <inheritdoc />
public override async Task<IList<SearchResult>> SearchAsync(SearchSuggestion suggestion, CancellationToken cancellationToken = default)
{
await _additionalLoadTask;
await LoadTask.Value;
cancellationToken.ThrowIfCancellationRequested();

var tempParams = new GeocodeParameters();
Expand All @@ -167,7 +149,7 @@ private SearchSuggestion SuggestResultToSearchSuggestion(SuggestResult r)
/// <inheritdoc/>
public override async Task<IList<SearchSuggestion>> SuggestAsync(string queryString, CancellationToken cancellationToken = default)
{
await _additionalLoadTask;
await LoadTask.Value;
cancellationToken.ThrowIfCancellationRequested();

SuggestParameters.PreferredSearchLocation = PreferredSearchLocation;
Expand Down Expand Up @@ -197,7 +179,7 @@ public override async Task<IList<SearchSuggestion>> SuggestAsync(string queryStr
/// <inheritdoc/>
public override async Task<IList<SearchResult>> SearchAsync(string queryString, CancellationToken cancellationToken = default)
{
await _additionalLoadTask;
await LoadTask.Value;
cancellationToken.ThrowIfCancellationRequested();

// Reset spatial parameters
Expand Down Expand Up @@ -230,7 +212,7 @@ public override async Task<IList<SearchResult>> SearchAsync(string queryString,
/// </summary>
public override async Task<IList<SearchResult>> RepeatSearchAsync(string queryString, Geometry.Envelope queryArea, CancellationToken cancellationToken = default)
{
await _additionalLoadTask;
await LoadTask.Value;
cancellationToken.ThrowIfCancellationRequested();

// Reset spatial parameters
Expand Down
Loading