Click or drag to resize

DownloadPreplannedOfflineMapParameters Class

Parameters used for creating a DownloadPreplannedOfflineMapJob.
Inheritance Hierarchy
SystemObject
  Esri.ArcGISRuntime.Tasks.OfflineDownloadPreplannedOfflineMapParameters

Namespace:  Esri.ArcGISRuntime.Tasks.Offline
Assembly:  Esri.ArcGISRuntime (in Esri.ArcGISRuntime.dll) Version: 100.9.0.0
Syntax
C#
public sealed class DownloadPreplannedOfflineMapParameters

The DownloadPreplannedOfflineMapParameters type exposes the following members.

Constructors
  NameDescription
Public methodDownloadPreplannedOfflineMapParameters
Initializes a new instance of the DownloadPreplannedOfflineMapParameters class.
Public methodDownloadPreplannedOfflineMapParameters(PreplannedMapArea)
Initializes a new instance of the DownloadPreplannedOfflineMapParameters class with the given PreplannedMapArea.
Top
Properties
  NameDescription
Public propertyContinueOnErrors
Gets or sets a flag indicating whether or not the DownloadPreplannedOfflineMapJob should continue running in the event of failure to take a layer offline.
Public propertyIncludeBasemap
Gets or sets a value indicating whether or not a basemap will be included in the offline map.
Public propertyPreplannedMapArea
Gets or sets the PreplannedMapArea that will be downloaded for offline use.
Public propertyReferenceBasemapDirectory
Gets or sets the path to a directory on the device where the local basemap file is located.
Public propertyReferenceBasemapFilename
Gets or sets the name of a local basemap file on the device which can be used rather than downloading an online basemap.
Public propertyCode exampleUpdateMode
Gets or sets a value that describes how the offline map will obtain feature updates from the online service.
Top
Examples

Android

Example Name: DownloadPreplannedMap

Take a map offline using a preplanned map area.

Code example screen shot.

C#
// Copyright 2019 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 Android.App;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Widget;
using ArcGISRuntime.Samples.Managers;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Tasks.Offline;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Debug = System.Diagnostics.Debug;
using Path = System.IO.Path;

namespace ArcGISRuntimeXamarin.Samples.DownloadPreplannedMap
{
    [Activity(ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        name: "Download preplanned map area",
        category: "Map",
        description: "Take a map offline using a preplanned map area.",
        instructions: "Select a map area from the Preplanned Map Areas list. Tap the button to download the selected area. The download progress will be shown in the Downloads list. When a download is complete, select it to display the offline map in the map view.",
        tags: new[] { "map area", "offline", "pre-planned", "preplanned" })]
    public class DownloadPreplannedMap : Activity
    {
        // Hold references to the UI controls.
        private MapView _myMapView;
        private LinearLayout _mapListView;
        private AlertDialog _progressView;
        private ProgressBar _progressBar;
        private TextView _helpLabel;
        private Button _showOnlineButton;

        // ID of a web map with preplanned map areas.
        private const string PortalItemId = "acc027394bc84c2fb04d1ed317aac674";

        // Folder to store the downloaded mobile map packages.
        private string _offlineDataFolder;

        // Task for taking map areas offline.
        private OfflineMapTask _offlineMapTask;

        // Hold onto the original map.
        private Map _originalMap;

        // Hold a list of available map areas.
        private readonly List<PreplannedMapArea> _mapAreas = new List<PreplannedMapArea>();

        // Most recently opened map package.
        private MobileMapPackage _mobileMapPackage;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            Title = "Download a preplanned map area";

            CreateLayout();
            Initialize();
        }

        private async void Initialize()
        {
            try
            {
                // The data manager provides a method to get a suitable offline data folder.
                _offlineDataFolder = Path.Combine(DataManager.GetDataFolder(), "SampleData", "DownloadPreplannedMapAreas");

                // If temporary data folder doesn't exists, create it.
                if (!Directory.Exists(_offlineDataFolder))
                {
                    Directory.CreateDirectory(_offlineDataFolder);
                }

                // Create a portal to enable access to the portal item.
                ArcGISPortal portal = await ArcGISPortal.CreateAsync();

                // Create the portal item from the portal item ID.
                PortalItem webMapItem = await PortalItem.CreateAsync(portal, PortalItemId);

                // Show the map.
                _originalMap = new Map(webMapItem);
                _myMapView.Map = _originalMap;

                // Create an offline map task for the web map item.
                _offlineMapTask = await OfflineMapTask.CreateAsync(webMapItem);

                // Find the available preplanned map areas.
                IReadOnlyList<PreplannedMapArea> preplannedAreas = await _offlineMapTask.GetPreplannedMapAreasAsync();

                // Load each item, then add it to the list of areas.
                foreach (PreplannedMapArea area in preplannedAreas)
                {
                    await area.LoadAsync();
                    _mapAreas.Add(area);
                }

                // Show the map areas in the UI.
                ConfigureMapsButtons();

                // Hide the loading indicator.
                _progressView.Dismiss();
            }
            catch (Exception ex)
            {
                // Something unexpected happened, show the error message.
                Debug.WriteLine(ex);
                new AlertDialog.Builder(this).SetMessage(ex.ToString()).SetTitle("There was an error.").Show();
            }
        }

        private void ShowOnlineClick(object sender, EventArgs e)
        {
            // Show the map.
            _myMapView.Map = _originalMap;

            // Disable the button.
            _showOnlineButton.Enabled = false;
        }

        private async Task DownloadMapAreaAsync(PreplannedMapArea mapArea)
        {
            // Close the current mobile package.
            _mobileMapPackage?.Close();

            // Set up UI for downloading.
            _progressBar.SetProgress(0, false);
            _progressView.SetMessage("Downloading map area...");
            _progressView.Show();

            // Create folder path where the map package will be downloaded.
            string path = Path.Combine(_offlineDataFolder, mapArea.PortalItem.Title);

            // If the area is already downloaded, open it.
            if (Directory.Exists(path))
            {
                try
                {
                    // Open the offline map package.
                    _mobileMapPackage = await MobileMapPackage.OpenAsync(path);

                    // Open the first map in the package.
                    _myMapView.Map = _mobileMapPackage.Maps.First();

                    // Update the UI.
                    _progressView.SetMessage("");
                    _progressView.Dismiss();
                    _helpLabel.Text = "Opened offline area.";
                    return;
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                    new AlertDialog.Builder(this).SetMessage(e.Message).SetTitle("Couldn't open offline area. Proceeding to take area offline.").Show();
                }
            }

            // Create download parameters.
            DownloadPreplannedOfflineMapParameters parameters = await _offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(mapArea);

            // Set the update mode to not receive updates.
            parameters.UpdateMode = PreplannedUpdateMode.NoUpdates;

            // Create the job.
            DownloadPreplannedOfflineMapJob job = _offlineMapTask.DownloadPreplannedOfflineMap(parameters, path);

            // Set up event to update the progress bar while the job is in progress.
            job.ProgressChanged += OnJobProgressChanged;

            try
            {
                // Download the area.
                DownloadPreplannedOfflineMapResult results = await job.GetResultAsync();

                // Set the update mode to not receive updates.
                parameters.UpdateMode = PreplannedUpdateMode.NoUpdates;

                // Handle possible errors and show them to the user.
                if (results.HasErrors)
                {
                    // Accumulate all layer and table errors into a single message.
                    string errors = "";

                    foreach (KeyValuePair<Layer, Exception> layerError in results.LayerErrors)
                    {
                        errors = $"{errors}\n{layerError.Key.Name} {layerError.Value.Message}";
                    }

                    foreach (KeyValuePair<FeatureTable, Exception> tableError in results.TableErrors)
                    {
                        errors = $"{errors}\n{tableError.Key.TableName} {tableError.Value.Message}";
                    }

                    // Show the message.
                    new AlertDialog.Builder(this).SetMessage(errors).SetTitle("Warning!").Show();
                }

                // Show the downloaded map.
                _myMapView.Map = results.OfflineMap;

                // Update the UI.
                _helpLabel.Text = "Downloaded offline area.";
                _showOnlineButton.Enabled = true;
            }
            catch (Exception ex)
            {
                // Report any errors.
                Debug.WriteLine(ex);
                new AlertDialog.Builder(this).SetMessage(ex.Message).SetTitle("Downloading map area failed.").Show();
            }
            finally
            {
                _progressBar.SetProgress(0, false);
                _progressView.SetMessage("");
                _progressView.Dismiss();
            }
        }

        private void OnJobProgressChanged(object sender, EventArgs e)
        {
            // Because the event is raised on a background thread, the dispatcher must be used to
            // ensure that UI updates happen on the UI thread.
            RunOnUiThread(() =>
            {
                // Update the UI with the progress.
                DownloadPreplannedOfflineMapJob downloadJob = sender as DownloadPreplannedOfflineMapJob;
                _progressBar.SetProgress(downloadJob.Progress, true);
                _progressView.SetMessage($"{downloadJob.Progress}%");
            });
        }

        private void DeleteButtonOnClick(object sender, EventArgs e)
        {
            try
            {
                // Set up UI for downloading.
                _progressView.SetMessage("Deleting map areas...");
                _progressView.Show();

                // Reset the map.
                _myMapView.Map = _originalMap;

                // Close the current mobile package.
                _mobileMapPackage?.Close();

                // Delete all data from the temporary data folder.
                Directory.Delete(_offlineDataFolder, true);
                Directory.CreateDirectory(_offlineDataFolder);

                // Update the UI.
                _helpLabel.Text = "Deleted offline areas.";
                _showOnlineButton.Enabled = false;
            }
            catch (Exception ex)
            {
                // Report the error.
                Debug.WriteLine(ex);
                new AlertDialog.Builder(this).SetMessage(ex.ToString()).SetTitle("Deleting map areas failed.").Show();
            }
            finally
            {
                _progressView.Dismiss();
            }
        }

        private void CreateLayout()
        {
            // Create a new vertical layout for the app.
            LinearLayout layout = new LinearLayout(this) { Orientation = Orientation.Vertical };

            // Add a help label.
            _helpLabel = new TextView(this);
            _helpLabel.Text = "Select a map area to take offline.";
            layout.AddView(_helpLabel);

            // Add space for adding options for each map.
            _mapListView = new LinearLayout(this) { Orientation = Orientation.Horizontal };
            layout.AddView(_mapListView);

            // Create a new layout for the buttons.
            LinearLayout buttonLayout = new LinearLayout(this) { Orientation = Orientation.Horizontal };

            // Add button for deleting map areas.
            Button deleteButton = new Button(this) { Text = "Delete offline areas" };
            deleteButton.Click += DeleteButtonOnClick;
            buttonLayout.AddView(deleteButton);

            // Add button for showing the original map.
            _showOnlineButton = new Button(this) { Text = "Show online map", Enabled = false };
            _showOnlineButton.Click += ShowOnlineClick;
            buttonLayout.AddView(_showOnlineButton);

            // Add the buttons to the layout.
            layout.AddView(buttonLayout);

            // Add the map view to the layout.
            _myMapView = new MapView(this);
            layout.AddView(_myMapView);

            // Show the layout in the app.
            SetContentView(layout);

            // Create the progress dialog display.
            _progressBar = new ProgressBar(this);
            _progressBar.SetProgress(0, true);
            AlertDialog.Builder builder = new AlertDialog.Builder(this).SetView(_progressBar);
            builder.SetCancelable(true);
            _progressView = builder.Create();
        }

        private async void ConfigureMapsButtons()
        {
            foreach (PreplannedMapArea mapArea in _mapAreas)
            {
                Button mapButton = new Button(this);

                mapButton.SetTextColor(Color.Black);
                mapButton.Background = Drawable.CreateFromStream(await mapArea.PortalItem.Thumbnail.GetEncodedBufferAsync(), "");
                mapButton.Text = mapArea.PortalItem.Title.Substring(0, 6);
                mapButton.Click += async (o, e) => { await DownloadMapAreaAsync(mapArea); };
                _mapListView.AddView(mapButton);

                LinearLayout.LayoutParams lparams = (LinearLayout.LayoutParams)mapButton.LayoutParameters;
                lparams.SetMargins(5, 5, 0, 5);
                mapButton.LayoutParameters = lparams;
            }
        }

        protected override void OnStop()
        {
            base.OnStop();

            // Close the current mobile package.
            _mobileMapPackage?.Close();
        }
    }
}
Examples

Xamarin Forms Android

Example Name: DownloadPreplannedMap

Take a map offline using a preplanned map area.

Code example screen shot.

C#
// Copyright 2019 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 ArcGISRuntime.Samples.Managers;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Tasks.Offline;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace ArcGISRuntimeXamarin.Samples.DownloadPreplannedMap
{
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        name: "Download preplanned map area",
        category: "Map",
        description: "Take a map offline using a preplanned map area.",
        instructions: "Select a map area from the Preplanned Map Areas list. Tap the button to download the selected area. The download progress will be shown in the Downloads list. When a download is complete, select it to display the offline map in the map view.",
        tags: new[] { "map area", "offline", "pre-planned", "preplanned" })]
    public partial class DownloadPreplannedMap : IDisposable
    {
        // ID of a web map with preplanned map areas.
        private const string PortalItemId = "acc027394bc84c2fb04d1ed317aac674";

        // Folder to store the downloaded mobile map packages.
        private string _offlineDataFolder;

        // Task for taking map areas offline.
        private OfflineMapTask _offlineMapTask;

        // Hold onto the original map.
        private Map _originalMap;

        // Hold list of map areas for use in the UI.
        private readonly List<PreplannedMapArea> _mapAreas = new List<PreplannedMapArea>();

        // Most recently opened map package.
        private MobileMapPackage _mobileMapPackage;

        public DownloadPreplannedMap()
        {
            InitializeComponent();
            Initialize();
        }

        private async void Initialize()
        {
            try
            {
                // The data manager provides a method to get a suitable offline data folder.
                _offlineDataFolder = Path.Combine(DataManager.GetDataFolder(), "SampleData", "DownloadPreplannedMapAreas");

                // If temporary data folder doesn't exists, create it.
                if (!Directory.Exists(_offlineDataFolder))
                {
                    Directory.CreateDirectory(_offlineDataFolder);
                }

                // Create a portal to enable access to the portal item.
                ArcGISPortal portal = await ArcGISPortal.CreateAsync();

                // Create the portal item from the portal item ID.
                PortalItem webMapItem = await PortalItem.CreateAsync(portal, PortalItemId);

                // Show the map.
                _originalMap = new Map(webMapItem);
                MyMapView.Map = _originalMap;

                // Create an offline map task for the web map item.
                _offlineMapTask = await OfflineMapTask.CreateAsync(webMapItem);

                // Find the available preplanned map areas.
                IReadOnlyList<PreplannedMapArea> preplannedAreas = await _offlineMapTask.GetPreplannedMapAreasAsync();

                // Load each item, then add it to the list of areas.
                foreach (PreplannedMapArea area in preplannedAreas)
                {
                    await area.LoadAsync();
                    _mapAreas.Add(area);
                }

                // Show the map areas in the UI.
                AreasList.ItemsSource = _mapAreas;

                // Hide the loading indicator.
                BusyIndicator.IsVisible = false;
            }
            catch (Exception ex)
            {
                // Something unexpected happened, show the error message.
                Debug.WriteLine(ex);
                await Application.Current.MainPage.DisplayAlert("There was an error.", ex.Message, "OK");
            }
        }

        private void ShowOnlineButton_Clicked(object sender, EventArgs e)
        {
            // Show the online map.
            MyMapView.Map = _originalMap;

            // Disable the button.
            ShowOnlineButton.IsEnabled = false;
        }

        private async Task DownloadMapAreaAsync(PreplannedMapArea mapArea)
        {
            // Close the current mobile package.
            _mobileMapPackage?.Close();

            // Set up UI for downloading.
            ProgressView.Progress = 0;
            BusyText.Text = "Downloading map area...";
            BusyIndicator.IsVisible = true;

            // Create folder path where the map package will be downloaded.
            string path = Path.Combine(_offlineDataFolder, mapArea.PortalItem.Title);

            // If the area is already downloaded, open it.
            if (Directory.Exists(path))
            {
                try
                {
                    // Open the offline map package.
                    _mobileMapPackage = await MobileMapPackage.OpenAsync(path);

                    // Open the first map in the package.
                    MyMapView.Map = _mobileMapPackage.Maps.First();

                    // Update the UI.
                    BusyText.Text = string.Empty;
                    BusyIndicator.IsVisible = false;
                    MessageLabel.Text = "Opened offline area.";
                    return;
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                    await Application.Current.MainPage.DisplayAlert("Couldn't open offline area. Proceeding to take area offline.", e.Message, "OK");
                }
            }

            // Create download parameters.
            DownloadPreplannedOfflineMapParameters parameters = await _offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(mapArea);

            // Set the update mode to not receive updates.
            parameters.UpdateMode = PreplannedUpdateMode.NoUpdates;

            // Create the job.
            DownloadPreplannedOfflineMapJob job = _offlineMapTask.DownloadPreplannedOfflineMap(parameters, path);

            // Set up event to update the progress bar while the job is in progress.
            job.ProgressChanged += OnJobProgressChanged;

            try
            {
                // Download the area.
                DownloadPreplannedOfflineMapResult results = await job.GetResultAsync();

                // Set the current mobile map package.
                _mobileMapPackage = results.MobileMapPackage;

                // Handle possible errors and show them to the user.
                if (results.HasErrors)
                {
                    // Accumulate all layer and table errors into a single message.
                    string errors = "";

                    foreach (KeyValuePair<Layer, Exception> layerError in results.LayerErrors)
                    {
                        errors = $"{errors}\n{layerError.Key.Name} {layerError.Value.Message}";
                    }

                    foreach (KeyValuePair<FeatureTable, Exception> tableError in results.TableErrors)
                    {
                        errors = $"{errors}\n{tableError.Key.TableName} {tableError.Value.Message}";
                    }

                    // Show the message.
                    await Application.Current.MainPage.DisplayAlert("Warning!", errors, "OK");
                }

                // Show the downloaded map.
                MyMapView.Map = results.OfflineMap;

                // Update the UI.
                ShowOnlineButton.IsEnabled = true;
                MessageLabel.Text = "Downloaded preplanned area.";
                DownloadButton.Text = "Display";
            }
            catch (Exception ex)
            {
                // Report any errors.
                Debug.WriteLine(ex);
                await Application.Current.MainPage.DisplayAlert("Downloading map area failed.", ex.Message, "OK");
            }
            finally
            {
                BusyText.Text = string.Empty;
                BusyIndicator.IsVisible = false;
            }
        }

        private void OnJobProgressChanged(object sender, EventArgs e)
        {
            // Because the event is raised on a background thread, the dispatcher must be used to
            // ensure that UI updates happen on the UI thread.
            Device.BeginInvokeOnMainThread(() =>
            {
                // Update the UI with the progress.
                DownloadPreplannedOfflineMapJob downloadJob = sender as DownloadPreplannedOfflineMapJob;
                ProgressView.Progress = downloadJob.Progress / 100.0;
                BusyText.Text = $"Downloading map... {downloadJob.Progress}%";
            });
        }

        private async void OnDownloadMapAreaClicked(object sender, EventArgs e)
        {
            if (AreasList.SelectedItem != null)
            {
                PreplannedMapArea selectedMapArea = AreasList.SelectedItem as PreplannedMapArea;
                await DownloadMapAreaAsync(selectedMapArea);
            }
        }

        private async void OnDeleteAllMapAreasClicked(object sender, EventArgs e)
        {
            try
            {
                // Set up UI for downloading.
                BusyText.Text = "Deleting downloaded map area...";
                BusyIndicator.IsVisible = true;

                // Reset the map.
                MyMapView.Map = _originalMap;

                // Close the current mobile package.
                _mobileMapPackage?.Close();

                // Delete all data from the temporary data folder.
                Directory.Delete(_offlineDataFolder, true);
                Directory.CreateDirectory(_offlineDataFolder);

                // Update the UI.
                MessageLabel.Text = "Deleted downloaded areas.";
                DownloadButton.Text = "Download";
                MessageLabel.Text = "Downloaded preplanned area.";
            }
            catch (Exception ex)
            {
                // Report the error.
                await Application.Current.MainPage.DisplayAlert("Deleting map areas failed.", ex.Message, "OK");
            }
            finally
            {
                BusyIndicator.IsVisible = false;
            }
        }
        private void AreaSelected(object sender, SelectedItemChangedEventArgs e)
        {
            PreplannedMapArea selectedMapArea = e.SelectedItem as PreplannedMapArea;
            string path = Path.Combine(_offlineDataFolder, selectedMapArea.PortalItem.Title);
            if (Directory.Exists(path))
            {
                DownloadButton.Text = "Display";
            }
            else
            {
                DownloadButton.Text = "Download";
            }
        }

        public void Dispose()
        {
            // Close the current mobile package.
            _mobileMapPackage?.Close();
        }
    }
}
XAML
<ContentPage
    x:Class="ArcGISRuntimeXamarin.Samples.DownloadPreplannedMap.DownloadPreplannedMap"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:esriUI="clr-namespace:Esri.ArcGISRuntime.Xamarin.Forms;assembly=Esri.ArcGISRuntime.Xamarin.Forms"
    xmlns:resources="clr-namespace:Forms.Resources;assembly=ArcGISRuntime">
    <RelativeLayout>
        <esriUI:MapView
            x:Name="MyMapView"
            BindingContext="{x:Reference Name=ResponsiveFormContainer}"
            Style="{StaticResource MapWithFormStyle}" />
        <resources:ResponsiveFormContainer x:Name="ResponsiveFormContainer">
            <StackLayout>

                <Label
                    x:Name="MessageLabel"
                    HorizontalTextAlignment="Center"
                    Text="Select an area, then download it." />
                <ListView
                    x:Name="AreasList"
                    HeightRequest="150"
                    ItemSelected="AreaSelected">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <OnPlatform x:TypeArguments="View">
                                    <On Platform="iOS, Android">
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="auto" />
                                                <ColumnDefinition Width="*" />
                                            </Grid.ColumnDefinitions>
                                            <Image
                                                Grid.RowSpan="2"
                                                Margin="-10,2,2,2"
                                                HeightRequest="70"
                                                Source="{Binding PortalItem.ThumbnailUri}" />
                                            <Label
                                                Grid.Column="1"
                                                Margin="10,0"
                                                Text="{Binding PortalItem.Title}"
                                                VerticalTextAlignment="Center" />
                                        </Grid>
                                    </On>
                                    <!--  Work around nasty Xamarin.Forms bug that affects UWP only - https://github.com/xamarin/Xamarin.Forms/issues/5188  -->
                                    <On Platform="UWP">
                                        <Label
                                            Margin="10,0"
                                            Text="{Binding PortalItem.Title}"
                                            VerticalTextAlignment="Center" />
                                    </On>
                                </OnPlatform>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Button
                        x:Name="DownloadButton"
                        Grid.Column="0"
                        Clicked="OnDownloadMapAreaClicked"
                        Text="Download" />
                    <Button
                        Grid.Column="1"
                        Clicked="OnDeleteAllMapAreasClicked"
                        Text="Delete all" />
                    <Button
                        x:Name="ShowOnlineButton"
                        Grid.Column="2"
                        Clicked="ShowOnlineButton_Clicked"
                        IsEnabled="False"
                        Text="Show Online" />
                </Grid>

            </StackLayout>
        </resources:ResponsiveFormContainer>
        <!--  Busy indication  -->
        <Grid
            x:Name="BusyIndicator"
            BackgroundColor="#807f7f7f"
            RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,
                                                                   Factor=1,
                                                                   Property=Height}"
            RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,
                                                                  Factor=1,
                                                                  Property=Width}">
            <Grid HorizontalOptions="Center" VerticalOptions="Center">
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                </Grid.RowDefinitions>
                <Label
                    x:Name="BusyText"
                    Margin="10"
                    FontSize="18"
                    TextColor="White" />
                <ProgressBar
                    x:Name="ProgressView"
                    Grid.Row="1"
                    HeightRequest="10"
                    HorizontalOptions="Center"
                    IsEnabled="True"
                    VerticalOptions="Center"
                    WidthRequest="100" />
            </Grid>
        </Grid>
    </RelativeLayout>
</ContentPage>
See Also
Additional Examples
Hyperlink to ExampleDescription
DownloadPreplannedMapTake a map offline using a preplanned map area.