Search

Download Samples Repository

Description

This sample shows how to use the Portal API to search for web maps on ArcGIS.com that match the search criteria.

"Desktop" "Store" "Phone" Available for Desktop, Store, Phone

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.PortalSearch"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
             xmlns:local="clr-namespace:ArcGISRuntime.Samples.Desktop">
    <Grid x:Name="layoutGrid">
        <Grid.Resources>
            <local:HtmlToTextConverter x:Key="HtmlToTextConverter" />
        </Grid.Resources>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" Margin="5">
            <ToolBar Height="auto" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="15" Background="LightGray">
                <TextBox x:Name="QueryText" Width="500" Text="World" KeyDown="QueryText_KeyDown" />
                <Button Content="Search" Click="DoSearch_Click" Margin="5,0,5,0" />
                <Separator />
                <Button x:Name="BackToResults" Content="Back to Results" Click="BackToResults_Click" Margin="5,0,5,0" />
                <Separator />
                <Button x:Name="SignInButton" Content="Sign In" Click="ShowSignIn_Click" Margin="5,0,5,0" />
            </ToolBar>
        </Grid>

        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>

            <ListBox x:Name="ResultsListBox" Background="Transparent" Grid.Row="2" Margin="10,3,0,0"
                     ScrollViewer.HorizontalScrollBarVisibility="Disabled">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>

                <ListBox.ItemTemplate>
                    <DataTemplate >
                        <Grid Width="350">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>

                            <TextBlock Text="{Binding Title}" TextTrimming="WordEllipsis"  Grid.Row="0"
                                       FontSize="12" Margin="5,5,5,0" TextWrapping="NoWrap" />

                            <StackPanel Orientation="Horizontal" Grid.Row="1">
                                <TextBlock Text="{Binding Type}" FontSize="10" Margin="5,0,0,0" />
                                <TextBlock Text="by" FontSize="10" Margin="2,0,0,0" />
                                <TextBlock Text="{Binding Owner}"  Margin="2,0,0,0" FontSize="10" />
                                <TextBlock Text="(last modified:" Margin="2,0,0,0" FontSize="10" />
                                <TextBlock Text="{Binding ModificationDate, StringFormat='MMMM dd, yyyy)'}" 
                                           FontSize="10" Margin="2,0,0,0" />
                            </StackPanel>

                            <Grid Grid.Row="2">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="85" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>

                                <Button Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Margin="5,0,10,0" Padding="1"
                                        Click="ItemButton_Click">
                                    <Border BorderBrush="Black" BorderThickness="2" >
                                        <Image Source="{Binding ThumbnailUri}" Stretch="UniformToFill" MaxHeight="80" MaxWidth="120" />
                                    </Border>
                                </Button>

                                <TextBlock Text="{Binding Description, Converter={StaticResource HtmlToTextConverter}}"
                                           TextTrimming="WordEllipsis" Grid.Row="0" Grid.Column="1"
                                           Height="85" TextWrapping="Wrap" FontSize="10" Width="235" Margin="5,5,5,1" />
                            </Grid>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <Grid x:Name="MapItemDetail" Grid.Column="1" Margin="20,0,0,0"
                  DataContext="{Binding ElementName=ResultsListBox, Path=SelectedItem}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <TextBlock Grid.Row="0" Text="{Binding Title}" TextTrimming="WordEllipsis" Margin="5" FontSize="18" />

                <Button Grid.Row="1" Margin="5,0,10,10" Padding="1" HorizontalAlignment="Left" Click="ItemButton_Click">
                    <Border BorderBrush="Black" BorderThickness="2" >
                        <Image Source="{Binding ThumbnailUri}" Stretch="UniformToFill" Width="200" Height="133" />
                    </Border>
                </Button>

                <ScrollViewer Grid.Row="2" Background="Transparent" Margin="5,0,0,0"
                              BorderThickness="0,1,0,0" HorizontalAlignment="Stretch" Padding="0"
                              VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
                    <Grid Margin="0,10,0,10">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="350" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="25" />
                            <RowDefinition Height="25" />
                            <RowDefinition Height="25" />
                            <RowDefinition Height="25" />
                        </Grid.RowDefinitions>

                        <TextBlock Grid.Row="0" Grid.Column="0" Text="Summary" />
                        <TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" 
                                   Text="{Binding Description, Converter={StaticResource HtmlToTextConverter}}" 
                                   TextTrimming="WordEllipsis" TextWrapping="Wrap" />

                        <TextBlock Grid.Row="1" Grid.Column="0" Text="Tags" Margin="0,10,0,10" VerticalAlignment="Top" />
                        <ListView Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="-7,0,0,0"
                                 ItemsSource="{Binding Tags}" Background="Transparent" BorderBrush="Transparent" 
                                 ScrollViewer.VerticalScrollBarVisibility="Disabled"
                                 ScrollViewer.HorizontalScrollBarVisibility="Disabled">
                            <ListView.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel Orientation="Horizontal" />
                                </ItemsPanelTemplate>
                            </ListView.ItemsPanel>
                        </ListView>

                        <TextBlock Grid.Row="2" Grid.Column="0" Text="Type" />
                        <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Type}" />

                        <TextBlock Grid.Row="3" Grid.Column="0" Text="Avg Rating" />
                        <TextBlock Grid.Row="3" Grid.Column="1" >
                            <Run Text="{Binding AvgRating, StringFormat='\{0:0.00}', Mode=OneWay}" />
                            <Run Text="{Binding NumRatings, StringFormat='\({0} ratings,', Mode=OneWay}" />
                            <Run Text="{Binding NumViews, StringFormat='\{0} views)', Mode=OneWay}"/>
                        </TextBlock>

                        <TextBlock Grid.Row="4" Grid.Column="0" Text="Last Modified" Margin="0,0,5,0" />
                        <TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding ModificationDate, StringFormat='MMMM dd, yyyy'}" />

                        <TextBlock Grid.Row="5" Grid.Column="0" Text="Owner" />
                        <TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding Owner}"/>
                    </Grid>
                </ScrollViewer>
            </Grid>

            <Grid x:Name="WebmapContent" Grid.ColumnSpan="2" Visibility="Collapsed" Background="#FF565656">
                <esri:MapView x:Name="MyMapView" />
            </Grid>
        </Grid>

        <Grid Name="ShadowGrid" Grid.RowSpan="2" VerticalAlignment="Stretch" 
              HorizontalAlignment="Stretch" Background="#66121212" Visibility="Collapsed" />

        <Grid Name="LoginGrid" MaxWidth="250" HorizontalAlignment="Right" VerticalAlignment="Top" Visibility="Collapsed"
              Margin="30"  Grid.Row="1">
            <Rectangle Stroke="DarkBlue" Fill="LightGray" Margin="-10" >
                <Rectangle.Effect>
                    <DropShadowEffect/>
                </Rectangle.Effect>
            </Rectangle>

            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>

                <TextBlock Text="Username" Grid.Column="0" Grid.Row="1" Margin="2" VerticalAlignment="Center" />
                <TextBox Name="UserTextBox" HorizontalAlignment="Right" Margin="2"  Grid.Column="1" Grid.Row="1" Width="140" />
                <TextBlock Text="Password" Grid.Column="0" Grid.Row="2" Margin="2" VerticalAlignment="Center" />
                <PasswordBox Name="PasswordTextBox" HorizontalAlignment="Right" Margin="2" Grid.Column="1" Grid.Row="2" Width="140" />
                <StackPanel Orientation="Horizontal"  Grid.Row="3" Grid.ColumnSpan="2" HorizontalAlignment="Right">
                    <Button Name="OK" Content="OK" Margin="0,5,0,5" Click="SignIn_Click" IsDefault="{Binding ElementName=LoginGrid, Path=IsVisible}" />
                    <Button Name="Cancel" Content="Cancel" Margin="10,5,0,5" Click="Cancel_Click" HorizontalAlignment="Right" />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</UserControl>
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Security;
using Esri.ArcGISRuntime.WebMap;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;

namespace ArcGISRuntime.Samples.Desktop
{
    /// <summary>
    /// This sample shows how to use the Portal API to search for web maps on ArcGIS.com that match the search criteria.
    /// </summary>
    /// <title>Search</title>
    /// <category>Portal</category>
    public partial class PortalSearch : UserControl
    {
        private const string DEFAULT_SERVER_URL = "https://www.arcgis.com/sharing/rest";
        private const string DEFAULT_TOKEN_URL = "https://www.arcgis.com/sharing/generateToken";

        private ArcGISPortal _portal;

        /// <summary>Construct Portal Search sample control</summary>
        public PortalSearch()
        {
            InitializeComponent();

            IdentityManager.Current.RegisterServer(
                new ServerInfo()
                {
                    ServerUri = DEFAULT_SERVER_URL,
                    TokenServiceUri = DEFAULT_TOKEN_URL,
                });
			IdentityManager.Current.ChallengeHandler = new ChallengeHandler(Challenge);

            Loaded += control_Loaded;
        }

        // Activate IdentityManager but don't accept any challenge.
        // User must use the 'SignIn' button for getting its own maps.
        private Task<Credential> Challenge(CredentialRequestInfo arg)
        {
            return Task.FromResult<Credential>(null);
        }

        // Initialize the display with a web map and search portal for basemaps
        private async void control_Loaded(object sender, RoutedEventArgs e)
        {
            _portal = await ArcGISPortal.CreateAsync();

            // Initial search on load
            DoSearch();
        }

        private void BackToResults_Click(object sender, RoutedEventArgs e)
        {
            ResetVisibility();
        }

        private void QueryText_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                DoSearch();
                e.Handled = true;
            }
        }

        private void DoSearch_Click(object sender, RoutedEventArgs e)
        {
            DoSearch();
        }

        private void ResetVisibility()
        {
            WebmapContent.Visibility = Visibility.Collapsed;
            BackToResults.IsEnabled = false;
            LoginGrid.Visibility = Visibility.Collapsed;
            ShadowGrid.Visibility = Visibility.Collapsed;
        }

        // Search arcgis.com for web maps matching the query text
        private async void DoSearch()
        {
            try
            {
                ResultsListBox.ItemsSource = null;
                ResetVisibility();
                if (QueryText == null || string.IsNullOrEmpty(QueryText.Text.Trim()))
                    return;

                var queryString = string.Format("{0} type:(\"web map\" NOT \"web mapping application\")", QueryText.Text.Trim());
                if (_portal.CurrentUser != null && _portal.ArcGISPortalInfo != null && !string.IsNullOrEmpty(_portal.ArcGISPortalInfo.Id))
                    queryString = string.Format("{0} orgid:(\"{1}\")", queryString, _portal.ArcGISPortalInfo.Id);

                var searchParameters = new SearchParameters()
                {
                    QueryString = queryString,
                    SortField = "avgrating",
                    SortOrder = QuerySortOrder.Descending,
                    Limit = 20
                };

                var result = await _portal.SearchItemsAsync(searchParameters);
                ResultsListBox.ItemsSource = result.Results;

                if (result.Results != null && result.Results.Count() > 0)
                    ResultsListBox.SelectedIndex = 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Sample Error");
            }
        }

        private async void ItemButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                BackToResults.IsEnabled = true;

                var item = ((Button)sender).DataContext as ArcGISPortalItem;
                var webmap = await WebMap.FromPortalItemAsync(item);
                var vm = await WebMapViewModel.LoadAsync(webmap, _portal);
                MyMapView.Map = vm.Map;

                WebmapContent.Visibility = Visibility.Visible;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Sample Error");
            }
        }

        #region Sign in/out
        private async void ShowSignIn_Click(object sender, RoutedEventArgs e)
        {
            if (SignInButton.Content.ToString() == "Sign In")
            {
                ShadowGrid.Visibility = Visibility.Visible;
                LoginGrid.Visibility = Visibility.Visible;
            }
            else //Sign Out
            {
                ResultsListBox.ItemsSource = null;

                var crd = IdentityManager.Current.FindCredential(DEFAULT_SERVER_URL);
                IdentityManager.Current.RemoveCredential(crd);

                _portal = await ArcGISPortal.CreateAsync(new Uri(DEFAULT_SERVER_URL));

                ResetVisibility();
                SignInButton.Content = "Sign In";

                DoSearch();
            }
        }

        private async void SignIn_Click(object sender, RoutedEventArgs e)
        {
            ResultsListBox.ItemsSource = null;

            try
            {
                var crd = await IdentityManager.Current.GenerateCredentialAsync(
                    DEFAULT_SERVER_URL, UserTextBox.Text, PasswordTextBox.Password);
                IdentityManager.Current.AddCredential(crd);

                _portal = await ArcGISPortal.CreateAsync(new Uri(DEFAULT_SERVER_URL));

                ResetVisibility();
                SignInButton.Content = "Sign Out";

                DoSearch();
            }
            catch
            {
                MessageBox.Show("Could not log in. Please check credentials.");
            }
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            LoginGrid.Visibility = Visibility.Collapsed;
            ShadowGrid.Visibility = Visibility.Collapsed;
        }
        #endregion
    }

    // Helper class sto get a description string from HTML content
    internal class HtmlToTextConverter : IValueConverter
    {
        private static string htmlLineBreakRegex = @"(<br */>)|(\[br */\])"; //@"<br(.)*?>";	// Regular expression to strip HTML line break tag
        private static string htmlStripperRegex = @"<(.|\n)*?>";	// Regular expression to strip HTML tags

        public static string GetHtmlToInlines(DependencyObject obj)
        {
            return (string)obj.GetValue(HtmlToInlinesProperty);
        }

        public static void SetHtmlToInlines(DependencyObject obj, string value)
        {
            obj.SetValue(HtmlToInlinesProperty, value);
        }

        // Using a DependencyProperty as the backing store for HtmlToInlinesProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HtmlToInlinesProperty =
          DependencyProperty.RegisterAttached("HtmlToInlines", typeof(string), typeof(HtmlToTextConverter), new PropertyMetadata(null, OnHtmlToInlinesPropertyChanged));

        private static void OnHtmlToInlinesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is Paragraph)
            {
                if (e.NewValue == null)
                    (d as Paragraph).Inlines.Clear();
                else
                {
                    var splits = Regex.Split(e.NewValue as string, htmlLineBreakRegex, RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
                    foreach (var line in splits)
                    {
                        string text = Regex.Replace(line, htmlStripperRegex, string.Empty);
                        Regex regex = new Regex(@"[ ]{2,}", RegexOptions.None);
                        if (!string.IsNullOrWhiteSpace(text))
                        {
                            text = regex.Replace(text, @" "); //Remove multiple spaces
                            text = text.Replace("&quot;", "\""); //Unencode quotes
                            text = text.Replace("&nbsp;", " "); //Unencode spaces
                            (d as Paragraph).Inlines.Add(new Run() { Text = text });
                            (d as Paragraph).Inlines.Add(new LineBreak());
                        }
                    }
                }
            }
        }

        private static string ToStrippedHtmlText(object input)
        {
            string retVal = string.Empty;

            if (input != null)
            {
                // Replace HTML line break tags with $LINEBREAK$:
                retVal = Regex.Replace(input as string, htmlLineBreakRegex, "", RegexOptions.IgnoreCase);
                // Remove the rest of HTML tags:
                retVal = Regex.Replace(retVal, htmlStripperRegex, string.Empty);
                //retVal.Replace("$LINEBREAK$", "\n");
                retVal = retVal.Trim();
            }

            return retVal;
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is string)
                return ToStrippedHtmlText(value);
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
Feedback on this topic?