Skip to content

Commit

Permalink
Search View (#380)
Browse files Browse the repository at this point in the history
* WIP: search

* WIP: WPF mostly working

* WIP code clean up and refactoring

* Finishes review of ported prototype work

* Behavior, nullability

* WPF appearance WIP

* Improve appearance of results without subtitles

* Improve repeat search behavior, result appearance

* WIP WPF theming and behavior

* Style and behavior updates

* Behavior tweaks, warnings, clean up

* Additional configuration options

* Warnings and performance

* Updated UWP implementation

* Update UWP to use popup

* Code cleanup

* UWP - Color and margin refinement

* XAML refactoring

* WIP: Forms implementation

* WIP Xamarin.Forms

* UI improvements for Forms SearchView

* Code cleanup, refactoring, doc, samples

* Additional doc

* Sample tidying

* Improvements from self-review

* Improves callout behavior for selected results

* Improves repeat search behavior, appearance

* Improves message appearance, localization support

* XAML formatting

* WIP: changes from review

* WIP: review changes

* Address warnings

* Enhanced WPF samples

* Improvements from enhanced testing

* UWP samples

* Forms sample updates and related improvements

* Update samples for formatting, exercise SearchMode

* Remove redundant sample

* Fix: placeholder doesn't appear on load, Forms

* Improves aspects of suggestion group header Forms

Includes fix for the key used for display suggestion group header text being linked away in release.

* Fixes formatting issue

* Code cleanup

* Correct spelling error
  • Loading branch information
nCastle1 authored Dec 1, 2021
1 parent 0cad5cd commit d87ee8b
Show file tree
Hide file tree
Showing 58 changed files with 6,144 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ There are two ways to add Toolkit to your project:
- [**OverviewMap**](https://esri.github.io/arcgis-toolkit-dotnet/overview-map.html): Displays an interactive inset map for a map or scene.
- **PopupViewer**: Display details and media, edit attributes, geometry and related records, and manage the attachments of features and graphics (popups are defined in the popup property of features and graphics).
- **ScaleLine**: Displays current scale reference.
- **[SearchView](https://esri.github.io/arcgis-toolkit-dotnet/search-view.html)**: Enables searching using one or more locators, with support for suggestions, automatic zooming, and custom search sources.
- **SymbolDisplay**: Renders a symbol in a control.
- **TimeSlider**: Allows interactively defining a temporal range (i.e. time extent) and animating time moving forward or backward. Can be used to manipulate the time extent in a MapView or SceneView.

Expand Down
6 changes: 6 additions & 0 deletions docs/controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ Displays current scale reference.

![ScaleLine](https://user-images.githubusercontent.com/1378165/73390077-3debb900-428a-11ea-8b2f-dfd4914a637e.png)

### SearchView

Enables searching using one or more locators, with support for suggestions, automatic zooming, and custom search sources.

![SearchView](https://user-images.githubusercontent.com/29742178/142301018-4bbeb0f2-3021-49a7-b5ec-f642c5700bd0.png)

### SymbolDisplay

Expand Down Expand Up @@ -94,6 +99,7 @@ Allows interactively defining a temporal range (i.e. time extent) and animating
|[OverviewMap](overview-map.md) ||||||
|PopupViewer ||||||
|ScaleLine ||||||
|[SearchView](search-view.md) ||||||
|SignInForm | | Preview | | | |
|SymbolDisplay ||||||
|TableOfContents | N/A | Preview | N/A | N/A | N/A |
Expand Down
62 changes: 62 additions & 0 deletions docs/search-view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Search View

Search View enables searching using one or more locators, with support for suggestions, automatic zooming, and custom search sources.

![image](https://user-images.githubusercontent.com/29742178/142301018-4bbeb0f2-3021-49a7-b5ec-f642c5700bd0.png)

> **NOTE**: Search View uses metered ArcGIS services by default, so you will need to configure an API key. See [Security and authentication documentation](https://developers.arcgis.com/documentation/mapping-apis-and-services/security/#api-keys) for more information.

## Features

- Updates search suggestions as you type
- Supports using the Esri world geocoder or any other ArcGIS locators
- Supports searching using custom search sources
- Supports searching multiple sources simultaneously
- Allows for customization of the display of search results
- Allows you to repeat a search within a defined area, and shows a button to enable that search when the view's viewpoint changes
- Separates the behavior (`SearchViewModel`) and the display (`SearchView`) to allow you to create a custom UI if needed

## Customization

The following properties enable customization of the view:

- `EnableAutomaticConfiguration` - Controls whether view is automatically configured for the attached GeoView's map or scene. By default, this will set up a single World Geocoder search source. In future releases, this behavior may be extended to support other web map configuration options.
- `EnableRepeatSearchHereButton` - Controls whether a 'Repeat Search Here' button is shown when the user navigates the attached GeoView after a search is completed.
- `EnableResultListView` - Controls whether a result list is displayed.
- `EnableIndividualResultDisplay` - Controls whether the result list is shown when there is only one result.
- `MutlipleResultZoomBuffer` - Controls the buffer distance around collection results when a GeoView is attached and a search has multiple results.

## Usage - WPF

```xaml
<Grid>
<esri:MapView x:Name="MyMapView" />
<esri:SearchView GeoView="{Binding ElementName=MyMapView}" />
</Grid>
```

## Usage - UWP

```xaml
<Grid>
<esri:MapView x:Name="MyMapView" />
<toolkit:SearchView GeoView="{Binding ElementName=MyMapView}" />
</Grid>
```

## Usage - Xamarin.Forms

SearchView shows results in a list on top of underlying content, so it is best to position the view near the top of the page, on top of the MapView or SceneView.

```xaml
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<esri:MapView x:Name="MyMapView" Grid.Row="1" Grid.RowSpan="2" />
<toolkit:SearchView GeoView="{Binding Source={Reference MyMapView}}" Grid.Row="0" Grid.RowSpan="2" />
</Grid>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<Page
x:Class="Esri.ArcGISRuntime.Toolkit.SampleApp.Samples.SearchView.SearchViewCustomizationSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:esri="using:Esri.ArcGISRuntime.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:Esri.ArcGISRuntime.Toolkit.UI.Controls"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<esri:MapView x:Name="MyMapView" />
<toolkit:SearchView x:Name="MySearchView" />
<Border
Width="200"
Margin="8"
Padding="4"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<CheckBox
x:Name="EnableGeoViewBindingCheck"
Checked="GeoViewConnection_Checked"
Content="Enable Binding to GeoView"
IsChecked="True"
Unchecked="GeoViewConnection_Checked" />
<CheckBox Content="Enable individual result display" IsChecked="{Binding ElementName=MySearchView, Path=EnableIndividualResultDisplay, Mode=TwoWay}" />
<CheckBox Content="Enable built-in repeat button" IsChecked="{Binding ElementName=MySearchView, Path=EnableRepeatSearchHereButton, Mode=TwoWay}" />
<CheckBox Content="Enable built-in result list" IsChecked="{Binding ElementName=MySearchView, Path=EnableResultListView, Mode=TwoWay}" />
<ComboBox
x:Name="SearchModeCombo"
HorizontalAlignment="Stretch"
Header="Search Result Mode:"
IsEditable="False"
SelectedIndex="0"
SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem Content="Automatic" />
<ComboBoxItem Content="Single" />
<ComboBoxItem Content="Multiple" />
</ComboBox>
<TextBlock FontWeight="SemiBold" Text="Text customization:" />
<TextBox Header="Search Tooltip" Text="{Binding ElementName=MySearchView, Path=SearchTooltipText, Mode=TwoWay}" />
<TextBox Header="Clear Tooltip" Text="{Binding ElementName=MySearchView, Path=ClearSearchTooltipText, Mode=TwoWay}" />
<TextBox Header="All Sources button text" Text="{Binding ElementName=MySearchView, Path=AllSourceSelectText, Mode=TwoWay}" />
<TextBox Header="Default Placeholder" Text="{Binding ElementName=MySearchView, Path=SearchViewModel.DefaultPlaceholder, Mode=TwoWay}" />
<TextBox Header="No result message" Text="{Binding ElementName=MySearchView, Path=NoResultMessage, Mode=TwoWay}" />
<TextBox Header="Repeat search button text" Text="{Binding ElementName=MySearchView, Path=RepeatSearchButtonText, Mode=TwoWay}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding ElementName=MySearchView, Path=RepeatSearchHereCommand, Mode=OneWay}"
Content="Repeat Search"
IsEnabled="{Binding ElementName=MySearchView, Path=SearchViewModel.IsEligibleForRequery, Mode=OneWay}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding ElementName=MySearchView, Path=ClearCommand, Mode=OneWay}"
Content="Clear Search" />
<ListView
DisplayMemberPath="DisplayTitle"
Header="Results:"
ItemsSource="{Binding ElementName=MySearchView, Path=SearchViewModel.Results, Mode=OneWay}"
SelectedItem="{Binding ElementName=MySearchView, Path=SearchViewModel.SelectedResult, Mode=TwoWay}" />
<ListView
DisplayMemberPath="DisplayName"
Header="Sources:"
ItemsSource="{Binding ElementName=MySearchView, Path=SearchViewModel.Sources, Mode=OneWay}"
SelectedItem="{Binding ElementName=MySearchView, Path=SearchViewModel.ActiveSource, Mode=TwoWay}" />
<Button
HorizontalAlignment="Stretch"
Click="AddDefaultLocator_Click"
Content="Add World Geocoder with Name:" />
<TextBox x:Name="GeocoderNameTextBox" Text="Name" />
<Button
HorizontalAlignment="Stretch"
Click="RemoveLocator_Click"
Content="Remove Last Search Source" />
</StackPanel>
</Border>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Toolkit.UI.Controls;
using System;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Esri.ArcGISRuntime.Toolkit.SampleApp.Samples.SearchView
{
public sealed partial class SearchViewCustomizationSample : Page
{
public SearchViewCustomizationSample()
{
InitializeComponent();
MyMapView.Map = new Map(BasemapStyle.ArcGISImagery);
MySearchView.GeoView = MyMapView;
}

private void GeoViewConnection_Checked(object sender, RoutedEventArgs e)
{
if (EnableGeoViewBindingCheck.IsChecked ?? false)
{
MySearchView.GeoView = MyMapView;
}
else
{
MySearchView.GeoView = null;
}
}

private async void AddDefaultLocator_Click(object sender, RoutedEventArgs e)
{
try
{
var source = await LocatorSearchSource.CreateDefaultSourceAsync();
source.DisplayName = GeocoderNameTextBox.Text;
MySearchView.SearchViewModel.Sources.Add(source);
}
catch (Exception ex)
{
await new MessageDialog(ex.Message, "Error").ShowAsync();
}
}

private void RemoveLocator_Click(object sender, RoutedEventArgs e)
{
if (MySearchView.SearchViewModel?.Sources?.Count > 0)
{
MySearchView.SearchViewModel.Sources.RemoveAt(MySearchView.SearchViewModel.Sources.Count - 1);
}
}

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
switch (SearchModeCombo.SelectedIndex)
{
case 0:
MySearchView.SearchViewModel.SearchMode = SearchResultMode.Automatic;
break;
case 1:
MySearchView.SearchViewModel.SearchMode = SearchResultMode.Single;
break;
case 2:
MySearchView.SearchViewModel.SearchMode = SearchResultMode.Multiple;
break;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Page
x:Class="Esri.ArcGISRuntime.Toolkit.SampleApp.Samples.SearchView.SearchViewMapSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:esri="using:Esri.ArcGISRuntime.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:Esri.ArcGISRuntime.Toolkit.UI.Controls"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<esri:MapView x:Name="MyMapView" />
<toolkit:SearchView GeoView="{Binding ElementName=MyMapView}" />
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Esri.ArcGISRuntime.Mapping;
using Windows.UI.Xaml.Controls;

namespace Esri.ArcGISRuntime.Toolkit.SampleApp.Samples.SearchView
{
public sealed partial class SearchViewMapSample : Page
{
public SearchViewMapSample()
{
InitializeComponent();
MyMapView.Map = new Map(BasemapStyle.ArcGISImagery);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Page
x:Class="Esri.ArcGISRuntime.Toolkit.SampleApp.Samples.SearchView.SearchViewSceneSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:esri="using:Esri.ArcGISRuntime.UI.Controls"
xmlns:toolkit="using:Esri.ArcGISRuntime.Toolkit.UI.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<esri:SceneView x:Name="MySceneView" />
<toolkit:SearchView GeoView="{Binding ElementName=MySceneView}" />
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Esri.ArcGISRuntime.Mapping;
using Windows.UI.Xaml.Controls;

namespace Esri.ArcGISRuntime.Toolkit.SampleApp.Samples.SearchView
{
public sealed partial class SearchViewSceneSample : Page
{
public SearchViewSceneSample()
{
InitializeComponent();
MySceneView.Scene = new Scene(BasemapStyle.ArcGISImagery);
}
}
}
21 changes: 21 additions & 0 deletions src/Samples/Toolkit.SampleApp.UWP/Toolkit.Samples.UWP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@
<Compile Include="Samples\PopupViewer\PopupViewerSample.xaml.cs">
<DependentUpon>PopupViewerSample.xaml</DependentUpon>
</Compile>
<Compile Include="Samples\SearchView\SearchViewMapSample.xaml.cs">
<DependentUpon>SearchViewMapSample.xaml</DependentUpon>
</Compile>
<Compile Include="Samples\SearchView\SearchViewSceneSample.xaml.cs">
<DependentUpon>SearchViewSceneSample.xaml</DependentUpon>
</Compile>
<Compile Include="Samples\SearchView\SearchViewCustomizationSample.xaml.cs">
<DependentUpon>SearchViewCustomizationSample.xaml</DependentUpon>
</Compile>
<Compile Include="Samples\SymbolDisplay\SymbolEditorSample.xaml.cs">
<DependentUpon>SymbolEditorSample.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -252,6 +261,18 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Samples\SearchView\SearchViewMapSample.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Samples\SearchView\SearchViewSceneSample.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Samples\SearchView\SearchViewCustomizationSample.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Samples\SymbolDisplay\SymbolEditorSample.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
Expand Down
Loading

0 comments on commit d87ee8b

Please sign in to comment.