Workflow: Create an app using a web map with layers (ahead of time)

Offline mapping app with a data layer

In this workflow, you will learn how to prepare a feature service and a web map, integrate the service into your web map, define areas in the map for offline use, then use it to create a partially offline app. This is also known as the ahead-of-time method because you are defining the offline areas in the map ahead of time.

Prerequisites

You need an account for ArcGIS Online or ArcGIS Enterprise to host data for offline use and get an access token. If you need an account, go to Get started.

Steps

1. Prepare the map and data

Import data to create a feature service

For this workflow, you will use the Santa Monica Parcels dataset to create a hosted feature layer for your web map.

  1. In your web browser, go to the Santa Monica Parcels item.

  2. Click the Download button to download the zip file locally. Do not unzip this file.

  3. Import the shapefile into ArcGIS using either a data management tool or a scripting API.

    In your web browser, go to ArcGIS.com and sign in with your ArcGIS Online account.

    1. In the top navigation bar, click Content.

    2. Click New item. To upload the Santa Monica Parcels shapefile, you can either:

      • Drag and drop the file.
      • Or, click Your device and navigate to the file path.
    3. Select Add Santa Monica Parcels.zip to publish the file as a hosted feature layer.

    4. In Fields, leave all fields at their default settings and click Next.

    5. In Location settings, leave the default settings and click Next.

    6. Set the following information in the item details pane:

      • Title: Santa Monica Parcels
      • Tags: Santa Monica Parcels.
      • Summary: Parcels in the Santa Monica Mountains.
    7. Click Next to create the new feature layer and feature service.

    1. Import the required libraries.
    2. Provide an access token.
    3. Create and publish a portal item.
    4. Handle the results.
    Expand
    Use dark colors for code blocksCopy
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # local path to shapefile zip file
    input_file_path = str(
        Path(__file__).parent / "Santa_Monica_Public_Parcels.zip"
    )
    
    # add the zip file as an item to portal
    shp_item = portal.content.add(
        {
            "title": "Santa Monica Public Parcels",
            "description": "Santa Monica public parcels",
            "tags": "Santa, Monica, public, parcels",
            "type": "Shapefile",
        },
        input_file_path,
    )
    
    # publish the item to create a hosted featurelayer
    shp_service = shp_item.publish(None)
    
    print(f"New item id : {shp_service.id, }, url: {shp_service.layers[0].url}")

The feature layer will look something like this:

Santa monica parcels feature layer

Set the feature styles

  1. Style the parcels based on the usetype field.

    Use the Visualization tab in the item page in ArcGIS.com to style the Santa Monica parcels layer.

    1. Go back to the item page > Visualization.

    2. In the left panel, click the Layers and select the Santa Monica parcels layer. In the right panel, click Styles.

    3. Click + Field, and add usetype.

    4. Under Pick a style, click Style options, update Types (unique symbols)

    5. Click on the symbol next to each of the use type values to update the symbol color.

    6. Set each of the usetype values to the following properties:

      • Fill Color:
        • Residential: #ffde3e
        • Commercial: #c29ed7
        • Industrial: #004c73
        • Government: #fc921f
        • Institutional: #149ece
        • Recreational: #267300
        • Miscellaneous: #b7814a
      style-screenshot
    7. Click the X to exit out of Symbol style.

    8. Click the pencil icon next to symbol style. Set the following properties for all the use types:

      • Fill transparency: 30%
      • Outline color: #ffffff
      • Outline transparency: 65%
      • Outline width: 1
      • Adjust width automatically: false
      style-screenshot
    9. Click the X to exit out of Symbol style. Then click Done twice.

    10. Click Save to save the style in the feature layer item.

The styled layer will look something like this:

Santa monica parcels feature layer

Manage service settings

In your portal, use the Settings tab to configure the service edit settings.

  1. In the item settings pane, scroll down to the Editing section.
  2. Click the Enable editing check box.
  3. Under the setting What kind of editing is allowed?, uncheck the Add and Delete privilege.
    • This will only allow editors to update existing features.
  4. Under the Update privilege, click Attributes only.
    • In our case, we only want editors to manage the feature attributes. They will be unable to remove or create new features.
  5. Click the Enable sync (required for offline use and collaboration) check box.
  6. Click Save.

Your edit settings should look like this:

Manage service settings

Create a web map with data layer

  1. In the item page of your feature layer, go to the Overview tab in the top menu bar.

  2. In the right panel, click Open in Map Viewer.

You should see a web map that looks something like this.

Save the web map

Now that you have a web map, you need to save it to your portal.

  1. In the left panel, click Save > Save as. At minimum, you need to provide a title and tags for your web map.

  2. In the left panel, click Share map.

  3. Select Everyone (public). Then, click Save.

Enable web map for offline use

  1. In your web browser, find the item ID at the end of the URL for the web map you just saved.

    • For example: 8ab76e9c5352400d87ca3315db9ba08e
  2. In a new browser tab, copy and paste the following URL and insert your item ID. This will return the item page for your web map, where you can configure it for offline use.

  3. Click Settings on the top bar of the item page. Settings

  4. Scroll down to the Offline menu. Offline section

  5. If you don't see the Offline enabled icon at the top right corner, click Check Compatibility and turn on Offline.

  6. Optionally, you can also manage advanced offline settings for your web map by clicking Options. These settings allow you to choose what data or updates mobile devices get and use a tile package for your offline basemap.

  7. Click Save. Your web map is enabled for offline use now.

Draw offline map areas

Now, you are going to define areas in your web map that you want to take offline, also known as offline map areas or preplanned map areas.

  1. Under Offline Map Areas, click Manage Offline Areas.

  2. In the left panel, click Create offline area.

  3. Draw an offline area on the map. You have two options to do this:

    • To draw a box around the area to take offline, click the Sketch rectangular map area button and draw a box on the map.
    • To draw a polygon to define the area you need to take offline, click the Sketch polygon map area button and draw the polygon on the map.
    Create offline areas

Manage offline map area settings

After defining your offline map areas, you can configure settings such as name, level of detail, and packaging schedule. Then, you will save the offline map area and an offline map package will be generated.

  1. In the Name field in the left panel, type a descriptive name for the offline map area.

  2. Open the Level of detail setting to change the quality and resolution of the downloaded raster or vector tile layers. You can move the slider to the right for more detail or to the left for less detail. Make sure that the small triangle icon is included in the scope of your slider.

  3. Open the Packaging schedule section to set the interval and time that you want the offline map area packages to be refreshed to capture changes to feature layer data. If you don't want to set an automatic refresh schedule, select Never from the drop-down menu.

  4. Open the Optimizations section to create offline map area packages for read-only use. Then, switch on the Enable packaged updates toggle button. Read-only packages are created based on the schedule you set in the previous step.

  5. Click Save.

  6. To create more offline areas for this map, click Create offline area and repeat the previous steps starting from Draw offline map areas. You can create up to 16 offline map areas per web map.

2. Build the app

Setup offline app

  1. Install and setup the ArcGIS Maps SDK for .NET on your development machine. Make sure you fulfill the SDK's system requirements.

  2. Follow the Display a map tutorial or download the completed solution to get a starter code for this workflow.

  3. Open the .sln file in Visual Studio.

    The Visual Studio solution, project, and the namespace for all classes currently use the name DisplayAMap. Follow the steps below if you prefer the name to reflect the current tutorial. These steps are not required, your code will still work if you keep the original name.

  4. Update the name for the solution and the project.

    • In Visual Studio, in the Solution Explorer, right-click the solution name and choose Rename. Provide the new name for your solution.
    • In the Solution Explorer, right-click the project name and choose Rename. Provide the new name for your project.
  5. Rename the namespace used by classes in the project.

    • In the Solution Explorer, expand the project node.
    • Double-click MapViewModel.cs in the Solution Explorer to open the file.
    • In the MapViewModel class, double-click the namespace name (DisplayAMap) to select it, and then right-click and choose Rename....
    • Provide the new name for the namespace.
    • Click Apply in the Rename: DisplayAMap window that appears in the upper-right of the code window. This will rename the namespace throughout your project.
  6. Build the project.

    • Choose Build > Build solution (or press F6).

Download and display the offline map

  1. In the Visual Studio > Solution Explorer, double-click MapViewModel.cs to open the file.

  2. Add additional required using statements at the top of the class.

    MapViewModel.cs
    Use dark colors for code blocks
    2 3 4 5 6 7 8 9 10 11 12 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13
    Add line.Add line.Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    
    using System;
    using System.Collections.Generic;
    using Esri.ArcGISRuntime.Portal;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    
    using System.Linq;
    using Esri.ArcGISRuntime.Mapping;
    using Esri.ArcGISRuntime.Tasks.Offline;
    
  3. Create an empty global variable _downloadLocation to store the path to the downloaded map area later.

    MapViewModel.cs
    Use dark colors for code blocks
    28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 29 30 31 32 33 34 35 36 37 38 39 40 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
    Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private string _downloadLocation;
    
            private Map? _map;
            public Map? Map
            {
                get { return _map; }
                set
                {
                    _map = value;
                    OnPropertyChanged();
                }
            }
    
  4. Modify the SetupMap function signature to private async returning a Task.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    Change lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange lineChange line
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  5. Remove the Map initializer from the SetupMap function. Because the map area will be downloaded from the web map, this is no longer needed.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  6. Inside MainWindow.xaml.cs, remove the viewpoint configuration.

    MainWindow.xaml.cs
    Use dark colors for code blocks
    36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 37 38 39 40 41 42 43 44 44 44 44
    Remove lineRemove line
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
            public MainWindow()
            {
                InitializeComponent();
    
                MapPoint mapCenterPoint = new MapPoint(-118.805, 34.027, SpatialReferences.Wgs84);
                MainMapView.SetViewpoint(new Viewpoint(mapCenterPoint, 100000));
    
            }
    
  7. Get the web map item ID from your ArcGIS Online, for example 8ab76e9c5352400d87ca3315db9ba08e.

  8. Create a Map from the web map using its item ID.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  9. Create an OfflineMapTask referencing the web map. This task object reads the offline properties of the web map and manages downloading an offline map from it.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  10. Use the OfflineMapTask to list any available ahead-of-time offline maps. In the ArcGIS Maps SDKs for Native Apps the ahead-of-time offline map areas are referred to as preplanned areas.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  11. Get a set of default DownloadPreplannedOfflineMapParameters. These parameters describe how the owner of the web map configured the offline map to be downloaded by default. You can modify the parameters to fine tune the downloaded offline map.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  12. Define a path to store the downloaded map area and store it in the global variable _downloadLocation.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  13. Use the parameters to create a DownloadPreplannedOfflineMapJob to download the offline map, specifying the download location.

    MapViewModel.cs
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
  14. Start the job and wait for it to complete, returning a Map that is ready for use.

    MapViewModel.cs
    Expand
    Use dark colors for code blocks
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 66 65 64 63 62 61 60 59 58 57 56 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task GetOfflinePreplannedMap()
            {
                var portal = await ArcGISPortal.CreateAsync();
                var portalItem = await PortalItem.CreateAsync(portal, "YOUR_ITEM_ID"); // Replace with your web map ID
                var map = new Map(portalItem);
    
                OfflineMapTask offlineMapTask = await OfflineMapTask.CreateAsync(map);
                IReadOnlyList<PreplannedMapArea> availableAreas = await offlineMapTask.GetPreplannedMapAreasAsync();
    
                if (availableAreas?.FirstOrDefault() is PreplannedMapArea area)
                {
                    DownloadPreplannedOfflineMapParameters downloadParameters = await offlineMapTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(area);
    
                    string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    _downloadLocation = System.IO.Path.Combine(documentsFolder, "OfflineMap");
    
                    DownloadPreplannedOfflineMapJob job = offlineMapTask.DownloadPreplannedOfflineMap(downloadParameters, _downloadLocation);
                    DownloadPreplannedOfflineMapResult result = await job.GetResultAsync();
    
                    if (result?.OfflineMap is Map offlineMap)
                    {
                        this.Map = offlineMap;
                    }
                }
            }
    
    Expand
  15. Click Debug > Start Debugging (or press F5 on the keyboard) to run the app.

Access the offline map

  1. Inside MapViewModel.cs, create a private async function returning a Task called AccessMap().

    MapViewModel.cs
    Use dark colors for code blocksCopy
    67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 68 69 70 70 70 70 70 70 70 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task AccessMap()
            {
    
            }
    
  2. Inside the function, create a MobileMapPackage that references the path to the downloaded offline map area.

    MapViewModel.cs
    Use dark colors for code blocks
    67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 68 69 70 71 72 72 72 72 72 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73
    Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task AccessMap()
            {
    
                var mobileMapPackage = await MobileMapPackage.OpenAsync(_downloadLocation);
    
            }
    
  3. Load the mobile map package and read the Map from it.

    MapViewModel.cs
    Use dark colors for code blocks
    67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 68 69 70 71 72 73 74 75 76 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77
    Add line.Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task AccessMap()
            {
    
                var mobileMapPackage = await MobileMapPackage.OpenAsync(_downloadLocation);
    
                await mobileMapPackage.LoadAsync();
    
                this.Map = mobileMapPackage.Maps.First();
    
            }
    
  4. The function is now ready to be called to access a previously downloaded offline map area. You can trigger this function from a UI button click or by calling it directly from the constructor.

  5. Click Debug > Start Debugging (or press F5 on the keyboard) to run the app.

Synchronize the offline map

  1. Inside MapViewModel.cs, create a private async function returning a Task called SynchronizeMap().

    MapViewModel.cs
    Use dark colors for code blocksCopy
    78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 79 80 81 81 81 81 81 81 81 81 81 82 82 82 82
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task SynchronizeMap()
            {
    
            }
    
  2. Create an OfflineMapSyncTask referencing the offline map.

    MapViewModel.cs
    Use dark colors for code blocks
    78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 79 80 81 82 83 83 83 83 83 83 83 84 84 84 84
    Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task SynchronizeMap()
            {
    
                OfflineMapSyncTask offlineMapSyncTask = await OfflineMapSyncTask.CreateAsync(Map);
    
            }
    
  3. Use the OfflineMapSyncTask to get default OfflineMapSyncParameters. Optionally modify these (for example, by specifying a synchronization direction).

    MapViewModel.cs
    Use dark colors for code blocks
    78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 79 80 81 82 83 84 85 85 85 85 85 86 86 86 86
    Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task SynchronizeMap()
            {
    
                OfflineMapSyncTask offlineMapSyncTask = await OfflineMapSyncTask.CreateAsync(Map);
    
                OfflineMapSyncParameters syncParameters = await offlineMapSyncTask.CreateDefaultOfflineMapSyncParametersAsync();
    
            }
    
  4. Use the parameters to create an OfflineMapSyncJob.

    MapViewModel.cs
    Use dark colors for code blocks
    78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 79 80 81 82 83 84 85 86 87 87 87 88 88 88 88
    Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task SynchronizeMap()
            {
    
                OfflineMapSyncTask offlineMapSyncTask = await OfflineMapSyncTask.CreateAsync(Map);
    
                OfflineMapSyncParameters syncParameters = await offlineMapSyncTask.CreateDefaultOfflineMapSyncParametersAsync();
    
                OfflineMapSyncJob syncJob = offlineMapSyncTask.SyncOfflineMap(syncParameters);
    
            }
    
  5. Start the OfflineMapSyncJob. If it completes without errors, the offline map and web map will be in sync.

    MapViewModel.cs
    Use dark colors for code blocks
    78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 79 80 81 82 83 84 85 86 87 88 89 90 90 90 90
    Add line.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
            private async Task SynchronizeMap()
            {
    
                OfflineMapSyncTask offlineMapSyncTask = await OfflineMapSyncTask.CreateAsync(Map);
    
                OfflineMapSyncParameters syncParameters = await offlineMapSyncTask.CreateDefaultOfflineMapSyncParametersAsync();
    
                OfflineMapSyncJob syncJob = offlineMapSyncTask.SyncOfflineMap(syncParameters);
    
                OfflineMapSyncResult syncResult = await syncJob.GetResultAsync();
    
            }
    
  6. The function is now ready to be called to synchronize an offline map. You can trigger this function from a UI button click or by calling it directly from the constructor.

  7. Click Debug > Start Debugging (or press F5 on the keyboard) to run the app.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.