S57 Search

Download Samples Repository

Description

This sample shows how to use the SearchAsync method to search an HydrographicS57Layer based on an input geometry, buffer value and object name.

"Desktop" "Store" Available for Desktop, Store

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.Symbology.Hydrographic.S57SearchSample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
			 xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
			 xmlns:hydro="clr-namespace:Esri.ArcGISRuntime.Hydrographic;assembly=Esri.ArcGISRuntime"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
	<Grid x:Name="LayoutGrid">
		<Grid.Resources>
			<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>

			<!-- selected point -->
			<esri:SimpleRenderer x:Key="PointSelectionRenderer">
				<esri:SimpleMarkerSymbol Color="Blue" />
			</esri:SimpleRenderer>
			<!-- selected polyline -->
			<esri:SimpleRenderer x:Key="LineSelectionRenderer">
				<esri:SimpleLineSymbol Color="Blue" Width="2" />
			</esri:SimpleRenderer>
			<!-- selected polygon -->
			<esri:SimpleLineSymbol x:Key="OutlineSelectionSymbol" Color="Black"/>
			<esri:SimpleFillSymbol x:Key="SelectionSymbol" Color="Blue" Style="DiagonalCross" Outline="{StaticResource OutlineSelectionSymbol}"/>
			<esri:SimpleRenderer x:Key="SelectionRendrer" Symbol="{StaticResource SelectionSymbol}"/>

			<esri:SimpleMarkerSymbol x:Key="BluePointSymbol" Color="Blue" Style="Circle" Size="15" />
			<esri:SimpleLineSymbol x:Key="GreenLineSymbol" Color="Green" Style="Solid" Width="4" />
			<esri:SimpleFillSymbol x:Key="RedFillSymbol" Color="Red" Style="DiagonalCross">
				<esri:SimpleFillSymbol.Outline>
					<esri:SimpleLineSymbol Color="Red" Style="Solid" Width="1" />
				</esri:SimpleFillSymbol.Outline>
			</esri:SimpleFillSymbol>
		</Grid.Resources>

		<esri:MapView x:Name="MyMapView" 
					  WrapAround="True"
					  LayerLoaded="MapView_LayerLoaded">
			<esri:Map>
				<esri:ArcGISTiledMapServiceLayer
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" />

				<!-- Using group layer to group all Hydrographic layers -->
				<esri:GroupLayer ID="Hydrographic">
					<hydro:HydrographicS57Layer ID="US1WCO1M" 
						Path="..\..\..\samples-data\symbology\s57-electronic-navigational-charts\us1wc01m\US1WC01M.000">
					</hydro:HydrographicS57Layer>
					<hydro:HydrographicS57Layer ID="US1WC07M" 
						Path="..\..\..\samples-data\symbology\s57-electronic-navigational-charts\us1wc07m\US1WC07M.000">
					</hydro:HydrographicS57Layer>
				</esri:GroupLayer>
			</esri:Map>
			<esri:MapView.GraphicsOverlays>
				<esri:GraphicsOverlay ID="graphicsOverlay" />
				<esri:GraphicsOverlay ID="polygonResultsOverlay" Renderer="{StaticResource SelectionRendrer}"/>
				<esri:GraphicsOverlay ID="lineResultsOverlay" Renderer="{StaticResource LineSelectionRenderer}"/>
				<esri:GraphicsOverlay ID="pointResultsOverlay" Renderer="{StaticResource PointSelectionRenderer}"/>
			</esri:MapView.GraphicsOverlays>
		</esri:MapView>

        <Border Background="White" BorderBrush="Black" BorderThickness="1" Margin="30" Padding="20"
                HorizontalAlignment="Right" VerticalAlignment="Top">
            <Grid>	
				<Grid.RowDefinitions>
					<RowDefinition Height="auto" />
					<RowDefinition Height="*" />
				</Grid.RowDefinitions>
				<TextBlock Text="Search results"
						   FontWeight="ExtraBold"
                           FontSize="14"
						   TextAlignment="Left" TextWrapping="Wrap" />
				<Border x:Name="NoResultsArea" Margin="10" Padding="20">
					<TextBlock Text="No search results."/>
				</Border>

				<!-- List of results -->
				<Grid x:Name="ResultsArea" Visibility="Collapsed"
					  Grid.Row="1">
					<Grid.RowDefinitions>
						<RowDefinition Height="*" />
						<RowDefinition Height="125"/>
					</Grid.RowDefinitions>
					<ListView x:Name="ResultList"
							  SelectionMode="Single"
							  SelectionChanged="ResultList_SelectionChanged">
						<ListView.ItemTemplate>
							<DataTemplate>
								<Grid>
									<StackPanel Margin="5">
										<StackPanel Orientation="Horizontal">
											<TextBlock Text="Acronym: " />
											<TextBlock Text="{Binding Path=Acronym}" />
										</StackPanel>
										<StackPanel Orientation="Horizontal">
											<TextBlock Text="Long Name: " />
											<TextBlock Text="{Binding Path=LongName}"/>
										</StackPanel>
										<StackPanel Orientation="Horizontal">
											<TextBlock Text="Cell Name: " />
											<TextBlock Text="{Binding Path=CellName}"/>
										</StackPanel>
										<StackPanel Orientation="Horizontal">
											<TextBlock Text="Composition Scale: " />
											<TextBlock Text="{Binding Path=CompositionScale}"/>
										</StackPanel>
									</StackPanel>
								</Grid>
							</DataTemplate>
						</ListView.ItemTemplate>
					</ListView>
					<!-- Attributes -->
					<ScrollViewer 
						HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"  
						Height="125" Width="290" Grid.Row="1">
						<DataGrid ItemsSource="{Binding ElementName=ResultList, Path=SelectedItem.Attributes}"  
							  AutoGenerateColumns="True" HeadersVisibility="All" 
                              Background="White">
						</DataGrid>
					</ScrollViewer>
				</Grid>
			</Grid>
		</Border>

		<!--Search area -->
		<Border x:Name="SearchArea" IsEnabled="False"
			Background="White" BorderBrush="Black" 
            HorizontalAlignment="Left" VerticalAlignment="Top"
			BorderThickness="1" Margin="30" Padding="20">
			<Border.Effect>
				<DropShadowEffect />
			</Border.Effect>
			<StackPanel>
				<!-- Draw search area -->
				<GroupBox>
					<GroupBox.Header>
						<TextBlock Text="Draw search area"/>
					</GroupBox.Header>
					<StackPanel>
						<TextBlock Text="Select geometry type" Margin="12,8" />

						<ComboBox SelectedItem="{Binding CurrentDrawShape}" Margin="8,0,8,2" Padding="4"
                              SelectionChanged="ComboBox_SelectionChanged">
							<esri:DrawShape>Point</esri:DrawShape>
							<esri:DrawShape>Polyline</esri:DrawShape>
							<esri:DrawShape>Polygon</esri:DrawShape>
							<esri:DrawShape>Rectangle</esri:DrawShape>
							<esri:DrawShape>Arrow</esri:DrawShape>
							<esri:DrawShape>Triangle</esri:DrawShape>
							<esri:DrawShape>Ellipse</esri:DrawShape>
							<esri:DrawShape>Circle</esri:DrawShape>
							<esri:DrawShape>LineSegment</esri:DrawShape>
						</ComboBox>

						<Button Content="Draw geometry"
								Click="AddSearchGeometry_Click"
								Margin="8"/>
					</StackPanel>
				</GroupBox>
				<!-- Search values -->
				<GroupBox>
					<GroupBox.Header>
						<TextBlock Text="Search values"/>
					</GroupBox.Header>
					<StackPanel>
						<StackPanel Orientation="Horizontal" >
							<TextBlock Text="Buffer:" Margin="2" Width="135"/>
							<TextBox x:Name="BufferValue" Text="" Width="150" Margin="2"/>
						</StackPanel>
						<StackPanel Orientation="Horizontal" >
							<TextBlock Text="Object Name (Acronym):" Margin="2" Width="135"/>
							<TextBox x:Name="SearchText" Text="" Width="150" Margin="2"/>
						</StackPanel>
					</StackPanel>
				</GroupBox>
                <StackPanel Orientation="Horizontal">
				<Button x:Name="searchBtn"
						IsEnabled="False"
						Content="Execute Search" 
						Click="Search_Click"
						Margin="6" Padding="6"
						HorizontalAlignment="Left" FontWeight="Bold"/>
                <Button x:Name="clearSearchBtn"
                        IsEnabled="False"
						Content="Clear Search" 
						Click="clearSearchBtn_Click"
						Margin="6" Padding="6"
						HorizontalAlignment="Right" FontWeight="Bold"/>
                </StackPanel>
			</StackPanel>
		</Border>

		<!-- Status area -->
		<Border Background="White" BorderBrush="Black" BorderThickness="2" Margin="25"
                HorizontalAlignment="Center" VerticalAlignment="Bottom"
                Visibility="{Binding ElementName=MyMapView, Path=Editor.IsActive, Converter={StaticResource BooleanToVisibilityConverter}}">
			<TextBlock Text="Draw the graphic shape on the map." Margin="8" FontSize="14" />
		</Border>
	</Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Hydrographic;
using Esri.ArcGISRuntime.Layers;
using Esri.ArcGISRuntime.Symbology;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.Samples.Desktop.Symbology.Hydrographic
{
    /// <summary>
    /// This sample shows how to use the SearchAsync method to search an HydrographicS57Layer based on an input geometry, buffer value and object name.
    /// </summary>
    /// <title>S57 Search </title>
    /// <category>Symbology</category>
    /// <subcategory>Hydrographic</subcategory>
    /// <requiresSymbols>true</requiresSymbols>
    public partial class S57SearchSample : UserControl, INotifyPropertyChanged
    {
        private DrawShape _currentDrawShape;
        private Geometry _searchGeometry;

        private GroupLayer _hydrographicLayers;
        private GraphicsOverlay _pointResultGraphicsOverlay;
        private GraphicsOverlay _lineResultGraphicsOverlay;
        private GraphicsOverlay _polygonResultGraphicsOverlay;
        private GraphicsOverlay _drawGraphicsOverlay;
        private ObservableCollection<S57FeatureObject> _searchResults;

        public S57SearchSample()
        {
            InitializeComponent();

            DataContext = this;
            _currentDrawShape = DrawShape.Point;
            _searchResults = new ObservableCollection<S57FeatureObject>();
            ResultList.ItemsSource = _searchResults;

            // Reference layers that are used
            _hydrographicLayers = MyMapView.Map.Layers.OfType<GroupLayer>().First();
            _drawGraphicsOverlay = MyMapView.GraphicsOverlays["graphicsOverlay"];
            _polygonResultGraphicsOverlay = MyMapView.GraphicsOverlays["polygonResultsOverlay"];
            _lineResultGraphicsOverlay = MyMapView.GraphicsOverlays["lineResultsOverlay"];
            _pointResultGraphicsOverlay = MyMapView.GraphicsOverlays["pointResultsOverlay"];
            ZoomToHydrographicLayers();
        }

        public DrawShape CurrentDrawShape
        {
            get { return _currentDrawShape; }
            set
            {
                _currentDrawShape = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("CurrentDrawShape"));
            }
        }

        // Zoom to combined extent of the group layer that contains all hydrographic layers
        private async void ZoomToHydrographicLayers()
        {
            try
            {
                // wait until all layers are loaded
                await MyMapView.LayersLoadedAsync();

                var extent = _hydrographicLayers.ChildLayers.First().FullExtent;

                // Create combined extent from child hydrographic layers
                foreach (var layer in _hydrographicLayers.ChildLayers)
                    extent = extent.Union(layer.FullExtent);

                // Zoom to full extent
                await MyMapView.SetViewAsync(extent);
                SearchArea.IsEnabled = true;
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }

        // Show error if loading layers fail
        private void MapView_LayerLoaded(object sender, LayerLoadedEventArgs e)
        {
            if (e.LoadError == null)
                return;

            MessageBox.Show(
                    string.Format("Error when loading layer. {0}", e.LoadError.ToString()),
                    "Error loading layer");
        }

        private async void ResultList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Clear previous selection
            _polygonResultGraphicsOverlay.Graphics.Clear();
            _lineResultGraphicsOverlay.Graphics.Clear();
            _pointResultGraphicsOverlay.Graphics.Clear();

            // When no results found, this is 0
            if (e.AddedItems.Count > 0)
            {
                // Using single mode so there is only one item
                var selectedFeatureObject = e.AddedItems[0] as S57FeatureObject;

                var selectedGeometry = selectedFeatureObject.Geometry;
                if (selectedGeometry is Polygon)
                {
                    _polygonResultGraphicsOverlay.Graphics.Add(new Graphic(selectedFeatureObject.Geometry));
                    _polygonResultGraphicsOverlay.Graphics[0].IsSelected = true;
                }
                else if (selectedGeometry is Polyline)
                {
                    _lineResultGraphicsOverlay.Graphics.Add(new Graphic(selectedFeatureObject.Geometry));
                    _lineResultGraphicsOverlay.Graphics[0].IsSelected = true;
                }
                else if (selectedGeometry is MapPoint)
                {
                    _pointResultGraphicsOverlay.Graphics.Add(new Graphic(selectedFeatureObject.Geometry));
                    _pointResultGraphicsOverlay.Graphics[0].IsSelected = true;
                }

                await MyMapView.SetViewAsync(selectedFeatureObject.Geometry.Extent);
            }
        }

        // Cancel the current shape drawing (if in Editor.RequestShapeAsync) when the shape type has changed
        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (MyMapView.Editor.IsActive)
                MyMapView.Editor.Cancel.Execute(null);
        }

        // Cancel the current shape drawing (if in Editor.RequestShapeAsync)
        // and draw new geometry
        private async void AddSearchGeometry_Click(object sender, RoutedEventArgs e)
        {
            if (MyMapView.Editor.IsActive)
                MyMapView.Editor.Cancel.Execute(null);

            _drawGraphicsOverlay.Graphics.Clear();
            searchBtn.IsEnabled = false;

            try
            {
                Symbol symbol = null;
                switch (CurrentDrawShape)
                {
                    case DrawShape.Point:
                        symbol = LayoutGrid.Resources["BluePointSymbol"] as Symbol;
                        break;

                    case DrawShape.LineSegment:
                    case DrawShape.Freehand:
                    case DrawShape.Polyline:
                        symbol = LayoutGrid.Resources["GreenLineSymbol"] as Symbol;
                        break;

                    case DrawShape.Arrow:
                    case DrawShape.Circle:
                    case DrawShape.Ellipse:
                    case DrawShape.Polygon:
                    case DrawShape.Rectangle:
                    case DrawShape.Triangle:
                        symbol = LayoutGrid.Resources["RedFillSymbol"] as Symbol;
                        break;
                }

                // wait for user to draw the shape
                _searchGeometry = await MyMapView.Editor.RequestShapeAsync(CurrentDrawShape, symbol);

                // add the new graphic to the graphic layer
                var graphic = new Graphic(_searchGeometry, symbol);
                _drawGraphicsOverlay.Graphics.Add(graphic);
                searchBtn.IsEnabled = true;
                clearSearchBtn.IsEnabled = true;
            }
            catch (TaskCanceledException)
            {
                searchBtn.IsEnabled = false;
                clearSearchBtn.IsEnabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error drawing graphic: " + ex.Message, "S57 Search Sample");
            }
        }

        // Execute search against hydrographic layers
        private async void Search_Click(object sender, RoutedEventArgs e)
        {
            // Clear previous results
            _searchResults.Clear();

            foreach (var layer in _hydrographicLayers.ChildLayers)
            {
                var hydroLayer = layer as HydrographicS57Layer;

                // Get buffer value
                double bufferDistance = 0;
                Double.TryParse(BufferValue.Text, out bufferDistance);

                // Search feature objects from layer based on geometry, buffer and object name
                var results = await hydroLayer.SearchAsync(MyMapView, _searchGeometry, bufferDistance, SearchText.Text);

                // Add results to results list
                if (results != null && results.Count > 0)
                {
                    foreach (var result in results)
                        _searchResults.Add(result);
                }
            }

            // Show results if there were any, other vice show no results
            if (_searchResults.Count > 0)
            {
                // Select first one
                ResultList.SelectedIndex = 0;
                ResultsArea.Visibility = Visibility.Visible;
                NoResultsArea.Visibility = Visibility.Collapsed;
            }
            else
            {
                ResultsArea.Visibility = Visibility.Collapsed;
                NoResultsArea.Visibility = Visibility.Visible;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        // Cancel the Editor and clear graphics and search results from the map
        private void clearSearchBtn_Click(object sender, RoutedEventArgs e)
        {

            if (MyMapView.Editor.IsActive)
                MyMapView.Editor.Cancel.Execute(null);

            _drawGraphicsOverlay.Graphics.Clear();
            _searchResults.Clear();

            SearchText.Clear();
            BufferValue.Clear();

            ResultsArea.Visibility = Visibility.Collapsed;
            NoResultsArea.Visibility = Visibility.Visible;

            searchBtn.IsEnabled = false;
            clearSearchBtn.IsEnabled = false;

        }
    }
}
Feedback on this topic?