Learn how to create and display a map

A map contains layers
In this tutorial, you create and display a map
The map and code will be used as the starting point for other 2D tutorials.
This tutorial builds a cross-platform app using the .NET Multi-platform App UI (.NET MAUI) framework. .NET MAUI allows you to build native cross-platform apps from a shared code base. If you’d prefer to build this app as a Windows desktop app, see the Windows Presentation Foundation (WPF) version of this tutorial.
Prerequisites
Before starting this tutorial:
-
You need an ArcGIS Location Platform or ArcGIS Online account.
-
Ensure your development environment meets the system requirements.
Optionally, you may want to install the ArcGIS Maps SDK for .NET to get access to project templates in Visual Studio (Windows only) and offline copies of the NuGet packages.
Set up authentication
To access the secure ArcGIS location services
You can implement API key authentication or user authentication in this tutorial. Compare the differences below:
API key authentication
- Users are not required to sign in.
- Requires creating an API key credential
API key credentials are an item that contains the parameters used to create and manage long-lived access tokens for API key authentication. They are a type of developer credential. with the correct privileges. - API keys
An API key is a long-lived access token created using API key credentials. They are valid for up to one year and are typically embedded directly into client applications. are long-lived access tokens. - Service usage is billed to the API key owner/developer.
- Simplest authentication method to implement.
- Recommended approach for new ArcGIS developers.
Learn more in API key authentication.
User authentication
- Users are required to sign in with an ArcGIS account
An ArcGIS account is an identity with a user type and set of privileges that can access specific ArcGIS products, tools, APIs, services, and resources. The main account types that can be used for development are an ArcGIS Location Platform account, ArcGIS Online account, and ArcGIS Enterprise account. ArcGIS Location Platform and ArcGIS Online accounts are also associated with a subscription. . - User accounts must have privilege
Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. to access the ArcGIS servicesA service, also known as an ArcGIS service, is software that supports an ArcGIS REST API and provides geospatial functionality or data. A service can be hosted by Esri or in ArcGIS Enterprise. used in application. - Requires creating OAuth credentials
OAuth credentials are an item that contains parameters required to implement user authentication or app authentication, including a .client_id,client_secret, and redirect URIs. They are a type of developer credential. - Application uses a redirect URL and client ID.
- Service usage is billed to the organization of the user signed into the application.
Learn more in User authentication.
To complete this tutorial, click on the tab in the switcher below for your authentication type of choice, either API key authentication or User authentication.
Create a new API key access token
-
Complete the Create an API key tutorial and create an API key with the following privilege(s)
Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. :- Privileges
- Location services > Basemaps
- Privileges
-
Copy and paste the API key access token into a safe location. It will be used in a later step.
Create new OAuth credentials to access the secure resources used in this tutorial.
-
Complete the Create OAuth credentials for user authentication tutorial to obtain a Client ID and Redirect URL.
A
Client IDuniquely identifies your app on the authenticating server. If the server cannot find an app with the provided Client ID, it will not proceed with authentication.The
Redirect URL(also referred to as a callback url) is used to identify a response from the authenticating server when the system returns control back to your app after an OAuth login. Since it does not necessarily represent a valid endpoint that a user could navigate to, the redirect URL can use a custom scheme, such asmy-app://auth. It is important to make sure the redirect URL used in your app’s code matches a redirect URL configured on the authenticating server. -
Copy and paste the Client ID and Redirect URL into a safe location. They will be used in a later step.
All users that access this application need account privileges
Develop or download
You have two options for completing this tutorial:
Option 1: Develop the code
Create a new Visual Studio Project
ArcGIS Maps SDK for .NET supports apps for Windows Presentation Framework (WPF), Universal Windows Platform (UWP), Windows UI Library (WinUI), and Multi-platform App UI (.NET MAUI). The instructions for this tutorial are specific to creating a .NET MAUI project using Visual Studio for Windows.
-
Start Visual Studio and create a new project.
- In the Visual Studio start screen, click Create a new project.
- Choose the .NET MAUI App template for C#. If you don’t see the template listed, you can find it by typing
MAUIinto the Search for templates text box. - Click Next.
- Provide required values in the Configure your new project panel:
- Project name:
DisplayAMap - Location:
choose a folder
- Project name:
- Click Next.
- Choose the .NET 9 as framework you intend to target.
- Click Create to create the project.
If you are developing with Visual Studio for Windows, ArcGIS Maps SDK for .NET provides a set of project templates for each supported .NET platform. These templates provide all of the code needed for a basic Model-View-ViewModel (MVVM) app. Install the ArcGIS Maps SDK for .NET Visual Studio Extension to add the templates to Visual Studio (Windows only). See Install and set up for details.
Add a reference to the API
-
Add a reference to the API by installing a NuGet package.
-
In Solution Explorer, right-click Dependencies and choose Manage NuGet Packages.
-
In the NuGet Package Manager window, ensure the selected Package source is
nuget.org(upper-right). -
Select the Browse tab and search for ArcGIS Maps SDK.
-
In the search results, select the appropriate package for your platform. For this tutorial project, choose the Esri.ArcGISRuntime.Maui NuGet package.
-
Confirm the Latest stable version of the package is selected in the Version dropdown.
-
Click Apply.
-
The Preview Changes dialog confirms any package(s) dependencies or conflicts. Review the changes and click OK to continue installing the packages.
-
Review the license information on the License Acceptance dialog and click I Accept to add the package(s) to your project.
-
In the Visual Studio Output window, ensure the packages were successfully installed.
-
Close the NuGet Package Manager window.
-
Correct minimum OS versions
The .NET MAUI App template may have operating system (OS) requirements below what ArcGIS Maps SDK for .NET requires for a .NET MAUI app. You must modify the minimum OS versions in your .csproj to satisfy the ArcGIS Maps SDK for .NET requirements.
-
In Visual Studio > Solution Explorer, double-click DisplayAMap to open the .csproj.
-
Modify the
<SupportedOSPlatformVersion>properties in the<PropertyGroup>as shown below. This reflects the minimum OS requirements for ArcGIS Maps SDK for .NET MAUI for the current release.DisplayAMap.csproj29 collapsed lines<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks><TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks><!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --><!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> --><!-- Note for MacCatalyst:The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;either BOTH runtimes must be indicated or ONLY macatalyst-x64. --><!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> --><OutputType>Exe</OutputType><RootNamespace>DisplayAMap</RootNamespace><UseMaui>true</UseMaui><SingleProject>true</SingleProject><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><!-- Display name --><ApplicationTitle>DisplayAMap</ApplicationTitle><!-- App Identifier --><ApplicationId>com.companyname.displayamap</ApplicationId><ApplicationIdGuid>8861a28a-1665-4549-825a-f7c5ee7dac07</ApplicationIdGuid><!-- Versions --><ApplicationDisplayVersion>1.0</ApplicationDisplayVersion><ApplicationVersion>1</ApplicationVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">16.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">28.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</SupportedOSPlatformVersion><TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</TargetPlatformMinVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion></PropertyGroup>32 collapsed lines<ItemGroup><!-- App Icon --><MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /><!-- Splash Screen --><MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /><!-- Images --><MauiImage Include="Resources\Images\*" /><MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /><!-- Custom Fonts --><MauiFont Include="Resources\Fonts\*" /><!-- Raw Assets (also remove the "Resources\Raw" prefix) --><MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /></ItemGroup><ItemGroup><PackageReference Include="Microsoft.Maui.Controls" Version="9.0.50" /><PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.50" /><PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.3" /><PackageReference Include="Esri.ArcGISRuntime.Maui" Version="200.8.2" /></ItemGroup><ItemGroup Condition="'$(TargetFramework)' == 'net9.0-windows10.0.19041.0'"><PackageReference Include="WinUIEx" Version="2.6.0" /></ItemGroup></Project>The .NET MAUI App template includes Tizen as a platform. ArcGIS Maps SDK for .NET does not support Tizen, so feel free to remove Tizen code and resources from the solution. This step is optional, your project will work fine if you keep it as-is.
-
Save and close the .csproj file.
Set developer credentials
To allow your app users to access ArcGIS Location Services
-
In the Solution Explorer, open MauiProgram.cs by double-clicking.
-
Add the following required
usingdirectives at the top of the file.MauiProgram.cs13 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){17 collapsed linesvar builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});#if DEBUGbuilder.Logging.AddDebug();#endifreturn builder.Build();}} -
Use the existing
buildervariable in theCreateMauiApp()function to callUseArcGISRuntime(). Use a lambda function to callUseApiKey()on aconfigparameter to set theApiKeyproperty onArcGISRuntimeEnvironment.MauiProgram.cs25 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});builder.UseArcGISRuntime(config =>{config.UseApiKey("YOUR_ACCESS_TOKEN");});#if DEBUGbuilder.Logging.AddDebug();#endif4 collapsed linesreturn builder.Build();}}
-
Update the
"YOUR_ACCESS_TOKEN"placeholder with the API key access token you created earlier. -
Save and close the MauiProgram.cs file.
Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
-
From the Visual Studio Project menu, choose Add class …. Name the class
ArcGISLoginPrompt.csthen click Add. The new class is added to your project and opens in Visual Studio. -
Select all the code in the new class and delete it.
-
Copy all of the code below and paste it into the
ArcGISLoginPrompt.csclass in your project.ArcGISLoginPrompt.cs// Copyright 2022 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 Esri.ArcGISRuntime.Security;using Esri.ArcGISRuntime.Portal;#if ANDROIDusing Android.App;using Application = Microsoft.Maui.Controls.Application;using Android.Content;using Android.Content.PM;#endifnamespace UserAuth{internal static class ArcGISLoginPrompt{private const string ArcGISOnlineUrl = "https://www.arcgis.com/sharing/rest";// Specify the Client ID and Redirect URL to use with OAuth authentication.// See the instructions here for creating OAuth app settings:// https://developers.arcgis.com/documentation/security-and-authentication/user-authentication/tutorials/create-oauth-credentials-user-auth/public const string AppClientId = @"YOUR_CLIENT_ID";private const string OAuthRedirectUrl = @"YOUR_REDIRECT_URL";public static async Task<bool> EnsureAGOLCredentialAsync(){bool loggedIn = false;Credential? currentCredential = AuthenticationManager.Current.FindCredential(new Uri(ArcGISOnlineUrl), AuthenticationType.Token);if (currentCredential != null){return true; // already logged in}try{// Create the portal, prompting the user to log in if they haven't already.var portal = await ArcGISPortal.CreateAsync(new Uri(ArcGISOnlineUrl), loginRequired: true);// If the user logged in successfully, the portal's User property will be non-null.loggedIn = portal.User != null;}catch (OperationCanceledException){// OAuth login was canceled, no need to display error to user.}catch (Exception ex){var mainPage = Application.Current?.Windows.FirstOrDefault()?.Page;if (mainPage != null){await mainPage.DisplayAlert("Login failed", ex.Message, "OK");}}return loggedIn;}public static void RegisterOAuthConfig(){var userConfig = new OAuthUserConfiguration(new Uri(ArcGISOnlineUrl), AppClientId, new Uri(OAuthRedirectUrl));AuthenticationManager.Current.OAuthUserConfigurations.Add(userConfig);AuthenticationManager.Current.OAuthAuthorizeHandler = new OAuthAuthorize();}}#region IOAuthAuthorizationHandler implementationpublic class OAuthAuthorize : IOAuthAuthorizeHandler{#if IOS || MACCATALYSTTaskCompletionSource<IDictionary<string, string>> _taskCompletionSource;public Task<IDictionary<string, string>> AuthorizeAsync(Uri serviceUri, Uri authorizeUri, Uri callbackUri){_taskCompletionSource = new TaskCompletionSource<IDictionary<string, string>>();Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(async () =>{try{var result = await WebAuthenticator.AuthenticateAsync(authorizeUri, callbackUri);_taskCompletionSource.TrySetResult(result.Properties);}catch (Exception ex){_taskCompletionSource.TrySetException(ex);}});return _taskCompletionSource.Task;}#elif ANDROIDpublic async Task<IDictionary<string, string>> AuthorizeAsync(Uri serviceUri, Uri authorizeUri, Uri callbackUri){var result = await WebAuthenticator.AuthenticateAsync(authorizeUri, callbackUri);return result.Properties;}#elif WINDOWSpublic async Task<IDictionary<string, string>> AuthorizeAsync(Uri serviceUri, Uri authorizeUri, Uri callbackUri){var result = await WinUIEx.WebAuthenticator.AuthenticateAsync(authorizeUri, callbackUri);return result.Properties;}#elsepublic async Task<IDictionary<string, string>> AuthorizeAsync(Uri serviceUri, Uri authorizeUri, Uri callbackUri){throw new NotImplementedException();}#endif}#if ANDROID[Activity(NoHistory = true, Exported = true, LaunchMode = LaunchMode.SingleTop)][IntentFilter(new[] { Intent.ActionView },Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },DataScheme = "my-app", DataHost = "auth")]public class WebAuthenticationCallbackActivity : WebAuthenticatorCallbackActivity{}#endif#endregion IOAuthAuthorizationHandler implementation} -
Add your values for the client ID (
AppClientId) and for the redirect URL (OAuthRedirectUrl). These are the user authentication settings you created in the Set up authentication step.ArcGISLoginPrompt.csinternal static class ArcGISLoginPrompt{private const string ArcGISOnlineUrl = "https://www.arcgis.com/sharing/rest";// Specify the Client ID and Redirect URL to use with OAuth authentication.// See the instructions here for creating OAuth app settings:// https://developers.arcgis.com/documentation/security-and-authentication/user-authentication/tutorials/create-oauth-credentials-user-auth/public const string AppClientId = @"YOUR_CLIENT_ID";private const string OAuthRedirectUrl = @"YOUR_REDIRECT_URL"; -
Save and close the
ArcGISLoginPrompt.csfile. -
In the Solution Explorer, open MauiProgram.cs by double-clicking.
-
Add the following required
usingdirectives at the top of the file.MauiProgram.cs13 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){17 collapsed linesvar builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});#if DEBUGbuilder.Logging.AddDebug();#endifreturn builder.Build();}} -
In the
CreateMauiApp()function, below the code that creates theMauiAppBuilder, callUseArcGISRuntimeon thebuildervariable. Also add a line to set the OAuth challenge handler (defined in the staticArcGISLoginPromptclass).MauiProgram.cs25 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});builder.UseArcGISRuntime(config =>{});// Set up the AuthenticationManager to use OAuth for secure ArcGIS Online requests.UserAuth.ArcGISLoginPrompt.RegisterOAuthConfig();#if DEBUGbuilder.Logging.AddDebug();#endif4 collapsed linesreturn builder.Build();}} -
Save and close the MauiProgram.cs file.
Best Practice: The OAuth credentials are stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
-
Follow the steps below to set up the .NET MAUI
WebAuthenticatorfor the desired platform(s). Note that these configuration settings assume your redirect URL begins withmy-app://. The .NET MAUI WebAuthenticator helps you implement browser-based authentication flows, which listen for a callback to a specific URL registered to the app.
Currently WebAuthenticator does not work on Windows without some additional work. See the .NET MAUI GitHub issue #2702 for details. There are a number of possible workarounds. For this tutorial, you will use a third-party nuget library.
-
In the Visual Studio > Solution Explorer, double-click the project node (DisplayAMap) to open the project file.
-
Include the following package reference in the DisplayAMap.csproj file.
DisplayAMap.csproj72 collapsed lines<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks><TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks><!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --><!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> --><!-- Note for MacCatalyst:The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;either BOTH runtimes must be indicated or ONLY macatalyst-x64. --><!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> --><OutputType>Exe</OutputType><RootNamespace>DisplayAMap</RootNamespace><UseMaui>true</UseMaui><SingleProject>true</SingleProject><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><!-- Display name --><ApplicationTitle>DisplayAMap</ApplicationTitle><!-- App Identifier --><ApplicationId>com.companyname.displayamap</ApplicationId><ApplicationIdGuid>8861a28a-1665-4549-825a-f7c5ee7dac07</ApplicationIdGuid><!-- Versions --><ApplicationDisplayVersion>1.0</ApplicationDisplayVersion><ApplicationVersion>1</ApplicationVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">16.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">28.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</SupportedOSPlatformVersion><TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</TargetPlatformMinVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion><WindowsSdkPackageVersion>10.0.22621.38</WindowsSdkPackageVersion><AllowUnsafeBlocks>true</AllowUnsafeBlocks></PropertyGroup><ItemGroup><!-- App Icon --><MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /><!-- Splash Screen --><MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /><!-- Images --><MauiImage Include="Resources\Images\*" /><MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /><!-- Custom Fonts --><MauiFont Include="Resources\Fonts\*" /><!-- Raw Assets (also remove the "Resources\Raw" prefix) --><MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /></ItemGroup><ItemGroup><PackageReference Include="Microsoft.Maui.Controls" Version="9.0.50" /><PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.50" /><PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.3" /><PackageReference Include="Esri.ArcGISRuntime.Maui" Version="200.8.2" /></ItemGroup><ItemGroup Condition="'$(TargetFramework)' == 'net9.0-windows10.0.19041.0'"><PackageReference Include="WinUIEx" Version="2.6.0" /></ItemGroup></Project> -
Also add the following settings to the
<PropertyGroup>in the project file.DisplayAMap.csproj29 collapsed lines<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks><TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks><!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --><!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> --><!-- Note for MacCatalyst:The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;either BOTH runtimes must be indicated or ONLY macatalyst-x64. --><!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> --><OutputType>Exe</OutputType><RootNamespace>DisplayAMap</RootNamespace><UseMaui>true</UseMaui><SingleProject>true</SingleProject><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><!-- Display name --><ApplicationTitle>DisplayAMap</ApplicationTitle><!-- App Identifier --><ApplicationId>com.companyname.displayamap</ApplicationId><ApplicationIdGuid>8861a28a-1665-4549-825a-f7c5ee7dac07</ApplicationIdGuid><!-- Versions --><ApplicationDisplayVersion>1.0</ApplicationDisplayVersion><ApplicationVersion>1</ApplicationVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">16.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">28.0</SupportedOSPlatformVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</SupportedOSPlatformVersion><TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</TargetPlatformMinVersion><SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion><WindowsSdkPackageVersion>10.0.22621.38</WindowsSdkPackageVersion><AllowUnsafeBlocks>true</AllowUnsafeBlocks></PropertyGroup>32 collapsed lines<ItemGroup><!-- App Icon --><MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /><!-- Splash Screen --><MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /><!-- Images --><MauiImage Include="Resources\Images\*" /><MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /><!-- Custom Fonts --><MauiFont Include="Resources\Fonts\*" /><!-- Raw Assets (also remove the "Resources\Raw" prefix) --><MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /></ItemGroup><ItemGroup><PackageReference Include="Microsoft.Maui.Controls" Version="9.0.50" /><PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.50" /><PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.3" /><PackageReference Include="Esri.ArcGISRuntime.Maui" Version="200.8.2" /></ItemGroup><ItemGroup Condition="'$(TargetFramework)' == 'net9.0-windows10.0.19041.0'"><PackageReference Include="WinUIEx" Version="2.6.0" /></ItemGroup></Project> -
Save and close the project file.
-
In your application constructor (
App.xaml.csfile), add the following code to perform an OAuth startup activation check (Windows only).App.xaml.csnamespace DisplayAMap;public partial class App : Application{public App(){#if WINDOWSif (WinUIEx.WebAuthenticator.CheckOAuthRedirectionActivation())return;#endifInitializeComponent();}protected override Window CreateWindow(IActivationState? activationState){// Create and return the main application windowreturn new Window(new AppShell());}} -
Save and close the
App.xaml.csfile.
For WinUI 3, the callback URI protocol needs to be included in the Package.appxmanifest file. The Protocol Name must match the URI scheme of the redirect URL on your ArcGIS Location Platform account
-
In the Visual Studio > Solution Explorer, navigate to the Platforms\Windows folder.
-
Right-click the Package.appxmanifest file and choose Open with … to open the file in an XML (Text) Editor then add the following lines.
Package.appxmanifest27 collapsed lines<?xml version="1.0" encoding="utf-8"?><Packagexmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"IgnorableNamespaces="uap rescap"><Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" /><mp:PhoneIdentity PhoneProductId="98DFA903-ED6A-46DB-8D46-B397B6A10215" PhonePublisherId="00000000-0000-0000-0000-000000000000"/><Properties><DisplayName>$placeholder$</DisplayName><PublisherDisplayName>User Name</PublisherDisplayName><Logo>$placeholder$.png</Logo></Properties><Dependencies><TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /><TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /></Dependencies><Resources><Resource Language="x-generate" /></Resources><Applications><Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"><uap:VisualElementsDisplayName="$placeholder$"Description="$placeholder$"Square150x150Logo="$placeholder$.png"Square44x44Logo="$placeholder$.png"BackgroundColor="transparent"><uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" /><uap:SplashScreen Image="$placeholder$.png" /></uap:VisualElements><Extensions><uap:Extension Category="windows.protocol"><uap:Protocol Name="my-app"/></uap:Extension></Extensions></Application></Applications>6 collapsed lines<Capabilities><rescap:Capability Name="runFullTrust" /></Capabilities></Package>
The iOS and Mac Catalyst platforms require the inclusion of your app’s callback URI pattern in their Info.plist files. The CFBundleURLSchemes value must match the URI scheme of the redirect URL on your ArcGIS Location Platform account.
-
In the Visual Studio > Solution Explorer, navigate to the Platforms\iOS folder.
-
Right-click the Info.plist file and choose Open with … to open the file in an XML (Text) Editor then add the following lines. Make the same edits in the Platforms\MacCatalyst\Info.plist file.
Info.plist29 collapsed lines<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>LSRequiresIPhoneOS</key><true/><key>UIDeviceFamily</key><array><integer>1</integer><integer>2</integer></array><key>UIRequiredDeviceCapabilities</key><array><string>arm64</string></array><key>UISupportedInterfaceOrientations</key><array><string>UIInterfaceOrientationPortrait</string><string>UIInterfaceOrientationLandscapeLeft</string><string>UIInterfaceOrientationLandscapeRight</string></array><key>UISupportedInterfaceOrientations~ipad</key><array><string>UIInterfaceOrientationPortrait</string><string>UIInterfaceOrientationPortraitUpsideDown</string><string>UIInterfaceOrientationLandscapeLeft</string><string>UIInterfaceOrientationLandscapeRight</string></array><key>XSAppIconAssets</key><string>Assets.xcassets/appicon.appiconset</string><key>CFBundleURLTypes</key><array><dict><key>CFBundleURLName</key><string>My App</string><key>CFBundleURLSchemes</key><array><string>my-app</string></array><key>CFBundleTypeRole</key><string>Editor</string></dict></array>3 collapsed lines</dict></plist>
For Android, the AndroidManifest.xml file must be updated to include the CustomTabsService, which is required by the WebAuthenticator.
-
In the Visual Studio > Solution Explorer, navigate to the Platforms\Android folder.
-
Right-click the AndroidManifest.xml file and choose Open with … to open the file in an XML (Text) Editor then add the following lines.
6 collapsed lines
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
<!--https://github.com/dotnet/maui/issues/3760#issuecomment-1046241094-->
<queries> <intent> <action android:name="android.support.customtabs.action.CustomTabsService" /> </intent> </queries>2 collapsed lines
</manifest>Android also requires the implementation of WebAuthenticatorCallbackActivity class, which is included in the ArcGISLoginPrompt.cs class you added above.
Remove default controls
The .NET MAUI App template provided by Visual Studio has default controls and logic. These must be removed to make room for the map view in your UI.
-
Open the MainPage.xaml file.
-
Remove the
ScrollViewcontainer (and all the controls it contains) from the current UI.MainPage.xaml<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"x:Class="DisplayAMap.MainPage"><ScrollView><VerticalStackLayoutSpacing="25"Padding="30,0"VerticalOptions="Center"><ImageSource="dotnet_bot.png"SemanticProperties.Description="Cute dot net bot waving hi to you!"HeightRequest="200"HorizontalOptions="Center" /><LabelText="Hello, World!"SemanticProperties.HeadingLevel="Level1"FontSize="32"HorizontalOptions="Center" /><LabelText="Welcome to .NET Multi-platform App UI"SemanticProperties.HeadingLevel="Level2"SemanticProperties.Description="Welcome to dot net Multi platform App U I"FontSize="18"HorizontalOptions="Center" /><Buttonx:Name="CounterBtn"Text="Click me"SemanticProperties.Hint="Counts the number of times you click"Clicked="OnCounterClicked"HorizontalOptions="Center" /></VerticalStackLayout></ScrollView></ContentPage> -
Open the MainPage.xaml.cs file.
-
Remove the
OnCounterClicked()function and thecountvariable.MainPage.xaml.csnamespace DisplayAMap;public partial class MainPage : ContentPage{int count = 0;public MainPage(){InitializeComponent();}private void OnCounterClicked(object sender, EventArgs e){count++;if (count == 1)CounterBtn.Text = $"Clicked {count} time";elseCounterBtn.Text = $"Clicked {count} times";SemanticScreenReader.Announce(CounterBtn.Text);}} -
Save and close MainPage.xaml and MainPage.xaml.cs.
Create a view model to store app logic
This app is the foundation for many following tutorials so it’s good to build it with a solid design. The Model-View-ViewModel (MVVM) design pattern provides an architecture that separates user interface elements (and related code) from the underlying app logic.
In the MVVM pattern, the model represents the data consumed in an app, the view is the user interface, and the view model contains the logic that binds the models and views together. The extra framework required for such a pattern might seem like a lot of work for a small project, but as the complexity of your project grows, a solid design can make your code much more maintainable and flexible.
In an ArcGIS app designed with MVVM, the map view
-
Add a new class that will define a view model for the project.
- Click Project > Add Class ….
- Name the new class
MapViewModel.cs. - Click Add to create the new class and add it to the project.
- The new class will open in Visual Studio.
-
Add required
usingstatements to the view model.MapViewModel.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Esri.ArcGISRuntime.Mapping;using Esri.ArcGISRuntime.Geometry;using System.ComponentModel;using System.Runtime.CompilerServices;using Map = Esri.ArcGISRuntime.Mapping.Map; -
Implement the
INotifyPropertyChangedinterface in theMapViewModelclass.This interface defines a
PropertyChangedevent that is used to notify clients (views) that a property of the view model has changed.MapViewModel.csnamespace DisplayAMap{internal class MapViewModel : INotifyPropertyChanged{ -
Inside the
MapViewModelclass, add code to implement thePropertyChangedevent.When a property of the view model changes, a call to
OnPropertyChangedwill raise this event.MapViewModel.cs28 collapsed lines// Copyright 2023 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//// https://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 System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Esri.ArcGISRuntime.Mapping;using Esri.ArcGISRuntime.Geometry;using System.ComponentModel;using System.Runtime.CompilerServices;using Map = Esri.ArcGISRuntime.Mapping.Map;namespace DisplayAMap{internal class MapViewModel : INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}2 collapsed lines} -
Define a new property on the view model called
Mapthat exposes aMapobject. When the property is set, callOnPropertyChanged.MapViewModel.cs28 collapsed lines// Copyright 2023 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//// https://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 System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Esri.ArcGISRuntime.Mapping;using Esri.ArcGISRuntime.Geometry;using System.ComponentModel;using System.Runtime.CompilerServices;using Map = Esri.ArcGISRuntime.Mapping.Map;namespace DisplayAMap{internal class MapViewModel : INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}private Map _map;public Map Map{get => _map;set{_map = value;OnPropertyChanged();}}}2 collapsed lines} -
Add a function to the
MapViewModelclass calledSetupMap. This function will create a new map and use it to set theMapproperty.MapViewModel.cs48 collapsed lines// Copyright 2023 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//// https://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 System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Esri.ArcGISRuntime.Mapping;using Esri.ArcGISRuntime.Geometry;using System.ComponentModel;using System.Runtime.CompilerServices;using Map = Esri.ArcGISRuntime.Mapping.Map;namespace DisplayAMap{internal class MapViewModel : INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}private Map _map;public Map Map{get => _map;set{_map = value;OnPropertyChanged();}}private void SetupMap(){// Create a new map with a 'topographic vector' basemap.Map = new Map(BasemapStyle.ArcGISTopographic);}4 collapsed lines}} -
Add code to set the map’s
InitialViewpointproperty to aViewpoint.MapViewModel.cs51 collapsed lines// Copyright 2023 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//// https://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 System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Esri.ArcGISRuntime.Mapping;using Esri.ArcGISRuntime.Geometry;using System.ComponentModel;using System.Runtime.CompilerServices;using Map = Esri.ArcGISRuntime.Mapping.Map;namespace DisplayAMap{internal class MapViewModel : INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}private Map _map;public Map Map{get => _map;set{_map = value;OnPropertyChanged();}}private void SetupMap(){// Create a new map with a 'topographic vector' basemap.Map = new Map(BasemapStyle.ArcGISTopographic);var mapCenterPoint = new MapPoint(-118.805, 34.027, SpatialReferences.Wgs84);Map.InitialViewpoint = new Viewpoint(mapCenterPoint, 100000);6 collapsed lines}}} -
Add a constructor to the class that calls
SetupMap()when a newMapViewModelis instantiated.When you write code like
MapViewModel newMapVM = new MapViewModel();to create a new instance, the class constructor is called. This is a good place to add code to set default values for properties and perform other setup tasks.MapViewModel.cs25 collapsed lines// Copyright 2023 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//// https://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 System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Esri.ArcGISRuntime.Mapping;using Esri.ArcGISRuntime.Geometry;using System.ComponentModel;using System.Runtime.CompilerServices;using Map = Esri.ArcGISRuntime.Mapping.Map;namespace DisplayAMap{internal class MapViewModel : INotifyPropertyChanged{public MapViewModel(){SetupMap();}32 collapsed linespublic event PropertyChangedEventHandler? PropertyChanged;protected void OnPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}private Map _map;public Map Map{get => _map;set{_map = value;OnPropertyChanged();}}private void SetupMap(){// Create a new map with a 'topographic vector' basemap.Map = new Map(BasemapStyle.ArcGISTopographic);var mapCenterPoint = new MapPoint(-118.805, 34.027, SpatialReferences.Wgs84);Map.InitialViewpoint = new Viewpoint(mapCenterPoint, 100000);}}} -
Save and close the MapViewModel.cs file.
Your MapViewModel is complete!
An advantage of using the MVVM design pattern is the ability to reuse code in a view model.
Because this API has a nearly-standard API surface across platforms, a view model written for one app typically works on all supported .NET platforms.
Next, you will set up a view in your project to consume the view model.
Add a map view
A MapView control is used to display a map. You will add a map view to your project UI and wire it up to consume the map that is defined in the MapViewModel.
-
Add required XML namespace and resource declarations to
MainPage.xaml.- Open MainPage.xaml and switch to the XAML view
- Inside the existing namespace declarations, add an
esriXML namespace for the ArcGIS controls and alocalXML namespace - Add XAML that defines a
MapViewModelinstance as a static resource
MainPage.xaml2 collapsed lines<?xml version="1.0" encoding="utf-8" ?><ContentPage x:Class="DisplayAMap.MainPage"xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"xmlns:local="clr-namespace:DisplayAMap"><ContentPage.Resources><local:MapViewModel x:Key="MapViewModel" /></ContentPage.Resources>3 collapsed lines</ContentPage> -
Add a
MapViewcontrol to MainPage.xaml and bind it to theMapViewModel.- Add XAML that defines a
MapViewcontrol namedMainMapView - Use data binding to set the
Mapproperty of the control using theMapViewModelresource
MainPage.xaml<?xml version="1.0" encoding="utf-8" ?><ContentPage x:Class="DisplayAMap.MainPage"xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"xmlns:local="clr-namespace:DisplayAMap"><ContentPage.Resources><local:MapViewModel x:Key="MapViewModel" /></ContentPage.Resources><esri:MapView x:Name="MainMapView" Map="{Binding Map, Source={StaticResource MapViewModel}}" /></ContentPage> - Add XAML that defines a
-
Save and close the MainPage.xaml file.
Run the app
Click Debug > Start Debugging (or press <F5> on the keyboard) to run the app. If your app uses user authentication, enter your ArcGIS Online credentials when prompted.
Deploy the app to a Windows, Mac, iOS, or Android device. You will see a map
Alternatively, you can download the tutorial solution, as follows.
Option 2: Download the solution
-
Click the Download solution link in the right-hand panel of the page.
-
Unzip the file to a location on your machine.
-
Open the
.slnfile in Visual Studio.
Since the downloaded solution does not contain authentication credentials, you must add the developer credentials that you created in the Set up authentication section.
Set developer credentials in the solution
To allow your app users to access ArcGIS location services
-
In the Solution Explorer, open MauiProgram.cs by double-clicking.
-
Update the call to
UseApiKey()on theconfigparameter to set your API key access token.MauiProgram.cs25 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});builder.UseArcGISRuntime(config =>{config.UseApiKey("YOUR_ACCESS_TOKEN");});#if DEBUGbuilder.Logging.AddDebug();#endif4 collapsed linesreturn builder.Build();}} -
Remove the line of code that sets the user authentication handler.
MauiProgram.cs25 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});builder.UseArcGISRuntime(config =>{config.UseApiKey("YOUR_ACCESS_TOKEN");});// Set up the AuthenticationManager to use OAuth for secure ArcGIS Online requests.UserAuth.ArcGISLoginPrompt.RegisterOAuthConfig();#if DEBUGbuilder.Logging.AddDebug();#endif4 collapsed linesreturn builder.Build();}} -
Save and close the MauiProgram.cs file.
Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
-
From the Visual Studio Solution explorer window, open the
ArcGISLoginPrompt.csfile. -
Set your values for the client ID (
OAuthClientID) and the redirect URL (OAuthRedirectUrl). These are the user authentication settings you created in the Set up authentication step.ArcGISLoginPrompt.csinternal static class ArcGISLoginPrompt{private const string ArcGISOnlineUrl = "https://www.arcgis.com/sharing/rest";// Specify the Client ID and Redirect URL to use with OAuth authentication.// See the instructions here for creating OAuth app settings:// https://developers.arcgis.com/documentation/security-and-authentication/user-authentication/tutorials/create-oauth-credentials-user-auth/public const string AppClientId = @"YOUR_CLIENT_ID";private const string OAuthRedirectUrl = @"YOUR_REDIRECT_URL"; -
In Visual Studio, in the Solution Explorer, click MauiProgram.cs to open the file.
-
Remove the line of code that sets an API key access token.
MauiProgram.cs25 collapsed lines// Copyright 2023 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//// https://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.namespace DisplayAMap;using Esri.ArcGISRuntime;using Esri.ArcGISRuntime.Maui;using Microsoft.Extensions.Logging;public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});builder.UseArcGISRuntime(config =>{config.UseApiKey("YOUR_ACCESS_TOKEN");});// Set up the AuthenticationManager to use OAuth for secure ArcGIS Online requests.UserAuth.ArcGISLoginPrompt.RegisterOAuthConfig();#if DEBUGbuilder.Logging.AddDebug();#endif4 collapsed linesreturn builder.Build();}} -
Save and close the MauiProgram.cs file.
Best Practice: The OAuth credentials are stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
Run the app
Click Debug > Start Debugging (or press <F5> on the keyboard) to run the app. If your app uses user authentication, enter your ArcGIS Online credentials when prompted.
Deploy the app to a Windows, Mac, iOS, or Android device. You will see a map
What’s next?
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: