private async void EditButtonClick(object sender, RoutedEventArgs e) { try { // Set the focus to the map view(close the flyout panel) DrawToolsFlyout.Hide(); // Allow the user to select a graphic Graphic editGraphic = await GetGraphicAsync(); if (editGraphic == null) { return; } // Let the user make changes to the graphic's geometry, await the result (updated geometry) Geometry newGeometry = await MyMapView.SketchEditor.StartAsync(editGraphic.Geometry); // Display the updated geometry in the graphic editGraphic.Geometry = newGeometry; } catch (TaskCanceledException) { // Ignore ... let the user cancel editing } catch (Exception ex) { // Report exceptions var dialog = new MessageDialog2("Error editing shape: " + ex.Message); await dialog.ShowAsync(); } }
// Search the IWA-secured portal for web maps and display the results in a list. private async void SearchSecureMapsButtonClick(object sender, RoutedEventArgs e) { try { // Get the value entered for the secure portal URL. string securedPortalUrl = SecurePortalUrlTextBox.Text.Trim(); // Make sure a portal URL has been entered in the text box. if (string.IsNullOrEmpty(securedPortalUrl)) { var dialog = new MessageDialog2("Please enter the URL of the secured portal.", "Missing URL"); await dialog.ShowAsync(); return; } // Create an instance of the IWA-secured portal, the user may be challenged for access. _iwaSecuredPortal = await ArcGISPortal.CreateAsync(new Uri(securedPortalUrl)); // Call a function to search the portal. SearchPortal(_iwaSecuredPortal); // Set a variable that indicates this is the secure portal. // When a map is loaded from the results, will need to know which portal it came from. _usingPublicPortal = false; } catch (Exception ex) { // Report errors (connecting to the secured portal, for example). MessagesTextBlock.Text = ex.Message; } }
private async Task ConfigureOfflineJobForBasemap(GenerateOfflineMapParameters parameters) { // Don't give the user a choice if there is no basemap specified. if (String.IsNullOrWhiteSpace(parameters.ReferenceBasemapFilename)) { return; } // Get the path to the basemap directory. string basemapBasePath = DataManager.GetDataFolder("85282f2aaa2844d8935cdb8722e22a93"); // Get the full path to the basemap by combining the name specified in the web map (ReferenceBasemapFilename) // with the offline basemap directory. string basemapFullPath = Path.Combine(basemapBasePath, parameters.ReferenceBasemapFilename); // If the offline basemap doesn't exist, proceed without it. if (!File.Exists(basemapFullPath)) { return; } // Create a dialog for getting the user's basemap choice. var dialog = new MessageDialog2("Use the offline basemap?", "Basemap choice"); // If the user selects OK, parameters.ReferenceBasemapDirectory will be set. dialog.Commands.Add(new UICommand("Yes", command => parameters.ReferenceBasemapDirectory = basemapBasePath)); // Do nothing otherwise. dialog.Commands.Add(new UICommand("No")); // Wait for the user to choose. await dialog.ShowAsync(); }
private async void DrawButtonClick(object sender, RoutedEventArgs e) { try { // Set the focus to the map view(close the flyout panel) DrawToolsFlyout.Hide(); // Let the user draw on the map view using the chosen sketch mode SketchCreationMode creationMode = Enum.Parse <SketchCreationMode>(SketchModeComboBox.SelectedItem as string); Esri.ArcGISRuntime.Geometry.Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, true); // Create and add a graphic from the geometry the user drew Graphic graphic = CreateGraphic(geometry); _sketchOverlay.Graphics.Add(graphic); // Enable/disable the clear and edit buttons according to whether or not graphics exist in the overlay ClearButton.IsEnabled = _sketchOverlay.Graphics.Count > 0; EditButton.IsEnabled = _sketchOverlay.Graphics.Count > 0; } catch (TaskCanceledException) { // Ignore ... let the user cancel drawing } catch (Exception ex) { // Report exceptions var dialog = new MessageDialog2("Error drawing graphic shape: " + ex.Message); await dialog.ShowAsync(); } }
private async void OpenFeaturesFromArcGISOnline(string itemId) { try { // Open a portal item containing a feature collection. ArcGISPortal portal = await ArcGISPortal.CreateAsync(); PortalItem collectionItem = await PortalItem.CreateAsync(portal, itemId); // Verify that the item is a feature collection. if (collectionItem.Type == PortalItemType.FeatureCollection) { // Create a new FeatureCollection from the item. FeatureCollection featureCollection = new FeatureCollection(collectionItem); // Create a layer to display the collection and add it to the map as an operational layer. FeatureCollectionLayer featureCollectionLayer = new FeatureCollectionLayer(featureCollection) { Name = collectionItem.Title }; MyMapView.Map.OperationalLayers.Add(featureCollectionLayer); } else { var messageDlg = new MessageDialog2("Portal item with ID '" + itemId + "' is not a feature collection.", "Feature Collection"); await messageDlg.ShowAsync(); } } catch (Exception ex) { var messageDlg = new MessageDialog2("Unable to open item with ID '" + itemId + "': " + ex.Message, "Error"); await messageDlg.ShowAsync(); } }
private async void Initialize() { // Create a map and add it to the view MyMapView.Map = new Map(Basemap.CreateLightGrayCanvas()); try { // LocalServer must not be running when setting the data path. if (LocalServer.Instance.Status == LocalServerStatus.Started) { await LocalServer.Instance.StopAsync(); } // Set the local data path - must be done before starting. On most systems, this will be C:\EsriSamples\AppData. // This path should be kept short to avoid Windows path length limitations. string tempDataPathRoot = Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.Windows)).FullName; string tempDataPath = Path.Combine(tempDataPathRoot, "EsriSamples", "AppData"); Directory.CreateDirectory(tempDataPath); // CreateDirectory won't overwrite if it already exists. LocalServer.Instance.AppDataPath = tempDataPath; // Start the local server instance await LocalServer.Instance.StartAsync(); // Get the path to the map package that will be served string datapath = GetDataPath(); // Create the Map Service from the data _localMapService = new LocalMapService(datapath); // Start the feature service await _localMapService.StartAsync(); // Get the url to the map service Uri myServiceUri = _localMapService.Url; // Create the layer from the url ArcGISMapImageLayer myImageLayer = new ArcGISMapImageLayer(myServiceUri); // Add the layer to the map MyMapView.Map.OperationalLayers.Add(myImageLayer); // Wait for the layer to load await myImageLayer.LoadAsync(); // Set the viewpoint on the map to show the data MyMapView.SetViewpoint(new Viewpoint(myImageLayer.FullExtent)); } catch (Exception ex) { var localServerTypeInfo = typeof(LocalMapService).GetTypeInfo(); var localServerVersion = FileVersionInfo.GetVersionInfo(localServerTypeInfo.Assembly.Location); var dlg = new MessageDialog2($"Please ensure that local server {localServerVersion.FileVersion} is installed prior to using the sample. The download link is in the description. Message: {ex.Message}", "Local Server failed to start"); _ = dlg.ShowAsync(); } }
private async void LoadWMTSLayer(bool uriMode) { try { // Create a new map. Map myMap = new Map(); // Get the basemap from the map. Basemap myBasemap = myMap.Basemap; // Get the layer collection for the base layers. LayerCollection myLayerCollection = myBasemap.BaseLayers; // Create an instance for the WMTS layer. WmtsLayer myWmtsLayer; // Define the Uri to the WMTS service. Uri wmtsUri = new Uri("https://sampleserver6.arcgisonline.com/arcgis/rest/services/WorldTimeZones/MapServer/WMTS"); if (uriMode) { // Create a WMTS layer using a Uri and provide an Id value. myWmtsLayer = new WmtsLayer(wmtsUri, "WorldTimeZones"); } else { // Define a new instance of the WMTS service. WmtsService myWmtsService = new WmtsService(wmtsUri); // Load the WMTS service. await myWmtsService.LoadAsync(); // Get the service information (i.e. metadata) about the WMTS service. WmtsServiceInfo myWmtsServiceInfo = myWmtsService.ServiceInfo; // Obtain the read only list of WMTS layer info objects. IReadOnlyList <WmtsLayerInfo> myWmtsLayerInfos = myWmtsServiceInfo.LayerInfos; // Create a WMTS layer using the first item in the read only list of WMTS layer info objects. myWmtsLayer = new WmtsLayer(myWmtsLayerInfos[0]); } // Add the WMTS layer to the layer collection of the map. myLayerCollection.Add(myWmtsLayer); // Assign the map to the MapView. MyMapView.Map = myMap; } catch (Exception ex) { var messageDlg = new MessageDialog2(ex.ToString(), "Error"); await messageDlg.ShowAsync(); } }
private async void ConvexHullListButton_Click(object sender, RoutedEventArgs e) { try { // Get the boolean value whether to create a single convex hull (true) or independent convex hulls (false). bool unionBool = (bool)ConvexHullListCheckBox.IsChecked; // Add the geometries of the two polygon graphics to a list of geometries. It will be used as the 1st // input parameter of the GeometryEngine.ConvexHull function. List <Geometry> inputListOfGeomtries = new List <Geometry> { _polygonGraphic1.Geometry, _polygonGraphic2.Geometry }; // Get the returned result from the convex hull operation. When unionBool = true there will be one returned // polygon, when unionBool = false there will be one convex hull returned per input geometry. IEnumerable <Geometry> convexHullGeometries = GeometryEngine.ConvexHull(inputListOfGeomtries, unionBool); // Loop through the returned geometries. foreach (Geometry oneGeometry in convexHullGeometries) { // Create a simple line symbol for the outline of the convex hull graphic(s). SimpleLineSymbol convexHullSimpleLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.Red, 10); // Create the simple fill symbol for the convex hull graphic(s) - comprised of a fill style, fill // color and outline. It will be a hollow (i.e.. see-through) polygon graphic with a thick red outline. SimpleFillSymbol convexHullSimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.Null, Color.Red, convexHullSimpleLineSymbol); // Create the graphic for the convex hull(s) - comprised of a polygon shape and fill symbol. Graphic convexHullGraphic = new Graphic(oneGeometry, convexHullSimpleFillSymbol) { // Set the Z index for the convex hull graphic(s) so that they appear below the initial input graphics // added earlier (polygon1 and polygon2). ZIndex = 0 }; // Add the convex hull graphic to the graphics overlay collection. _graphicsOverlay.Graphics.Add(convexHullGraphic); } // Disable the button after has been used. ConvexHullListCheckBox.IsEnabled = false; ConvexHullListButton.IsEnabled = false; } catch (Exception ex) { // Display an error message if there is a problem generating convex hull operation. var theMessageDialog = new MessageDialog2("Geometry Engine Failed: " + ex.Message); await theMessageDialog.ShowAsync(); } }
private async Task QueryStateFeature(string stateName) { try { // Create a query parameters that will be used to Query the feature table QueryParameters queryParams = new QueryParameters(); // Trim whitespace on the state name to prevent broken queries string formattedStateName = stateName.Trim().ToUpper(); // Construct and assign the where clause that will be used to query the feature table queryParams.WhereClause = "upper(STATE_NAME) LIKE '%" + formattedStateName + "%'"; // Query the feature table FeatureQueryResult queryResult = await _featureTable.QueryFeaturesAsync(queryParams); // Cast the QueryResult to a List so the results can be interrogated List <Feature> features = queryResult.ToList(); if (features.Any()) { // Create an envelope. EnvelopeBuilder envBuilder = new EnvelopeBuilder(SpatialReferences.WebMercator); foreach (Feature feature in features) { // Add the extent of each matching feature to the envelope. envBuilder.UnionOf(feature.Geometry.Extent); // Select each feature. _featureLayer.SelectFeature(feature); } // Zoom to the extent of the selected feature(s). await MyMapView.SetViewpointGeometryAsync(envBuilder.ToGeometry(), 50); } else { var message = new MessageDialog2("State Not Found!", "Add a valid state name."); await message.ShowAsync(); } } catch (Exception ex) { var message = new MessageDialog2("Sample error: " + ex, "An error occurred"); await message.ShowAsync(); } }
private async Task <IFeatureSet> GetGeodatabaseVersionsAsync() { // Results will be returned as a feature set IFeatureSet results = null; // Create new geoprocessing task GeoprocessingTask listVersionsTask = await GeoprocessingTask.CreateAsync(new Uri(ListVersionsUrl)); // Create default parameters that are passed to the geoprocessing task GeoprocessingParameters listVersionsParameters = await listVersionsTask.CreateDefaultParametersAsync(); // Create job that handles the communication between the application and the geoprocessing task GeoprocessingJob listVersionsJob = listVersionsTask.CreateJob(listVersionsParameters); try { // Execute analysis and wait for the results GeoprocessingResult analysisResult = await listVersionsJob.GetResultAsync(); // Get results from the outputs GeoprocessingFeatures listVersionsResults = (GeoprocessingFeatures)analysisResult.Outputs["Versions"]; // Set results results = listVersionsResults.Features; } catch (Exception ex) { // Error handling if something goes wrong if (listVersionsJob.Status == JobStatus.Failed && listVersionsJob.Error != null) { var message = new MessageDialog2("Executing geoprocessing failed. " + listVersionsJob.Error.Message, "Geoprocessing error"); await message.ShowAsync(); } else { var message = new MessageDialog2("An error occurred. " + ex.ToString(), "Sample error"); await message.ShowAsync(); } } finally { // Set the UI to indicate that the geoprocessing is not running SetBusy(false); } return(results); }
private async void ConvexHullButton_Click(object sender, RoutedEventArgs e) { try { // Create a multi-point geometry from the user tapped input map points. Multipoint inputMultipoint = new Multipoint(_inputPointCollection); // Get the returned result from the convex hull operation. Geometry convexHullGeometry = GeometryEngine.ConvexHull(inputMultipoint); // Create a simple line symbol for the outline of the convex hull graphic(s). SimpleLineSymbol convexHullSimpleLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.Blue, 4); // Create the simple fill symbol for the convex hull graphic(s) - comprised of a fill style, fill // color and outline. It will be a hollow (i.e.. see-through) polygon graphic with a thick red outline. SimpleFillSymbol convexHullSimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.Null, Color.Red, convexHullSimpleLineSymbol); // Create the graphic for the convex hull - comprised of a polygon shape and fill symbol. Graphic convexHullGraphic = new Graphic(convexHullGeometry, new Dictionary <string, object>() { { "Type", "Hull" } }, convexHullSimpleFillSymbol) { ZIndex = 1 }; // Remove any existing convex hull graphics from the overlay. foreach (Graphic g in new List <Graphic>(_graphicsOverlay.Graphics)) { if ((string)g.Attributes["Type"] == "Hull") { _graphicsOverlay.Graphics.Remove(g); } } // Add the convex hull graphic to the graphics overlay. _graphicsOverlay.Graphics.Add(convexHullGraphic); // Disable the button after has been used. ConvexHullButton.IsEnabled = false; } catch (System.Exception ex) { // Display an error message if there is a problem generating convex hull operation. var theMessageDialog = new MessageDialog2("Geometry Engine Failed: " + ex.Message); await theMessageDialog.ShowAsync(); } }
private async void MyMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e) { try { // Get the input map point (in the map's coordinate system, State Plane for North Central Texas). MapPoint tapMapPoint = e.Location; // Check if the point coordinates are within the spatial reference envelope. bool withinValidExent = GeometryEngine.Contains(_spatialReferenceArea, tapMapPoint); // If the input point is not within the valid extent for the spatial reference, warn the user and return. if (!withinValidExent) { var dialog = new MessageDialog2("Location is not valid to buffer using the defined spatial reference.", "Out of bounds"); await dialog.ShowAsync(); return; } // Get the buffer radius (in miles) from the text box. double bufferDistanceMiles = Convert.ToDouble(BufferDistanceMilesTextBox.Text); // Use a helper method to get the buffer distance in feet (unit that's used by the spatial reference). double bufferDistanceFeet = LinearUnits.Miles.ConvertTo(LinearUnits.Feet, bufferDistanceMiles); // Create a simple marker symbol (red circle) to display where the user tapped/clicked on the map. SimpleMarkerSymbol tapSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Red, 10); // Create a new graphic to show the tap location. Graphic tapGraphic = new Graphic(tapMapPoint, tapSymbol) { // Specify a z-index value on the point graphic to make sure it draws on top of the buffer polygons. ZIndex = 2 }; // Store the specified buffer distance as an attribute with the graphic. tapGraphic.Attributes["distance"] = bufferDistanceFeet; // Add the tap point graphic to the buffer graphics overlay. MyMapView.GraphicsOverlays["buffers"].Graphics.Add(tapGraphic); } catch (Exception ex) { // Display an error message. await new MessageDialog2(ex.Message, "Error creating buffer point").ShowAsync(); } }
private async void Open_Click(object sender, RoutedEventArgs e) { // Get the portal item Id from the user. string collectionItemId = CollectionItemIdTextBox.Text.Trim(); // Make sure an Id was entered. if (String.IsNullOrEmpty(collectionItemId)) { var messageDlg = new MessageDialog2("Please enter a portal item ID", "Feature Collection ID"); await messageDlg.ShowAsync(); return; } // Call a function to add the feature collection from the specified portal item. OpenFeaturesFromArcGISOnline(collectionItemId); }
private async void MyMapView_GeoViewTapped(object sender, Esri.ArcGISRuntime.UI.Controls.GeoViewInputEventArgs e) { try { // Normalize the tapped point. var centralizedPoint = (MapPoint)GeometryEngine.NormalizeCentralMeridian(e.Location); // Add the map point to the list that will be used by the GeometryEngine.ConvexHull operation. _inputPointCollection.Add(centralizedPoint); // Check if there are at least three points. if (_inputPointCollection.Count > 2) { // Enable the button for creating hulls. ConvexHullButton.IsEnabled = true; } // Create a simple marker symbol to display where the user tapped/clicked on the map. The marker symbol // will be a solid, red circle. SimpleMarkerSymbol userTappedSimpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Red, 10); // Create a new graphic for the spot where the user clicked on the map using the simple marker symbol. Graphic userTappedGraphic = new Graphic(e.Location, new Dictionary <string, object> { { "Type", "Point" } }, userTappedSimpleMarkerSymbol) { ZIndex = 0 }; // Set the Z index for the user tapped graphic so that it appears above the convex hull graphic(s) added later. userTappedGraphic.ZIndex = 1; // Add the user tapped/clicked map point graphic to the graphic overlay. _graphicsOverlay.Graphics.Add(userTappedGraphic); } catch (System.Exception ex) { // Display an error message if there is a problem adding user tapped graphics. var theMessageDialog = new MessageDialog2("Can't add user tapped graphic!" + ex.Message); await theMessageDialog.ShowAsync(); } }
private async void CutButton_Click(object sender, RoutedEventArgs e) { try { // Cut the polygon geometry with the polyline, expect two geometries. Geometry[] cutGeometries = GeometryEngine.Cut(_lakeSuperiorPolygonGraphic.Geometry, (Polyline)_countryBorderPolylineGraphic.Geometry); // Create a simple line symbol for the outline of the Canada side of Lake Superior. SimpleLineSymbol canadaSideSimpleLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Null, System.Drawing.Color.Blue, 0); // Create the simple fill symbol for the Canada side of Lake Superior graphic - comprised of a fill style, fill color and outline. SimpleFillSymbol canadaSideSimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.ForwardDiagonal, System.Drawing.Color.Green, canadaSideSimpleLineSymbol); // Create the graphic for the Canada side of Lake Superior - comprised of a polygon shape and fill symbol. Graphic canadaSideGraphic = new Graphic(cutGeometries[0], canadaSideSimpleFillSymbol); // Add the Canada side of the Lake Superior graphic to the graphics overlay collection. _graphicsOverlay.Graphics.Add(canadaSideGraphic); // Create a simple line symbol for the outline of the USA side of Lake Superior. SimpleLineSymbol usaSideSimpleLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Null, System.Drawing.Color.Blue, 0); // Create the simple fill symbol for the USA side of Lake Superior graphic - comprised of a fill style, fill color and outline. SimpleFillSymbol usaSideSimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.ForwardDiagonal, System.Drawing.Color.Yellow, usaSideSimpleLineSymbol); // Create the graphic for the USA side of Lake Superior - comprised of a polygon shape and fill symbol. Graphic usaSideGraphic = new Graphic(cutGeometries[1], usaSideSimpleFillSymbol); // Add the USA side of the Lake Superior graphic to the graphics overlay collection. _graphicsOverlay.Graphics.Add(usaSideGraphic); // Disable the button after has been used. CutButton.IsEnabled = false; } catch (System.Exception ex) { // Display an error message if there is a problem generating cut operation. var theMessageDialog = new MessageDialog2("Geometry Engine Failed: " + ex.Message); await theMessageDialog.ShowAsync(); } }
private async void StopEditTransaction(object sender, RoutedEventArgs e) { // Create a new dialog that prompts for commit, rollback, or cancel var promptDialog = new MessageDialog2("Commit your edits to the local geodatabase or rollback to discard them.", "Stop Editing"); UICommand commitCommand = new UICommand("Commit"); UICommand rollbackCommand = new UICommand("Rollback"); UICommand cancelCommand = new UICommand("Cancel"); promptDialog.Options = MessageDialogOptions.None; promptDialog.Commands.Add(commitCommand); promptDialog.Commands.Add(rollbackCommand); promptDialog.Commands.Add(cancelCommand); // Ask the user if they want to commit or rollback the transaction (or cancel to keep working in the transaction) IUICommand cmd = await promptDialog.ShowAsync(); if (cmd == commitCommand) { // See if there is a transaction active for the geodatabase if (_localGeodatabase.IsInTransaction) { // If there is, commit the transaction to store the edits (this will also end the transaction) _localGeodatabase.CommitTransaction(); MessageTextBlock.Text = "Edits were committed to the local geodatabase."; } } else if (cmd == rollbackCommand) { // See if there is a transaction active for the geodatabase if (_localGeodatabase.IsInTransaction) { // If there is, rollback the transaction to discard the edits (this will also end the transaction) _localGeodatabase.RollbackTransaction(); MessageTextBlock.Text = "Edits were rolled back and not stored to the local geodatabase."; } } else { // For 'cancel' don't end the transaction with a commit or rollback } }
private async void ClipButton_Click(object sender, RoutedEventArgs e) { try { // Remove the Colorado graphic from the input geometries graphics overlay collection. That way it will be easier // to see the clip versions of the GeometryEngine.Clip operation. _inputGeometriesGraphicsOverlay.Graphics.Remove(_coloradoGraphic); // Loop through each graphic in the input geometries for the clip operation. foreach (Graphic oneGraphic in _inputGeometriesGraphicsOverlay.Graphics) { // Perform the clip operation. The first parameter of the clip operation will always be the Colorado graphic. // The second parameter of the clip operation will be one of the 3 different clip geometries (_outsideGraphic, // _containedGraphic, or _intersectingGraphic). Geometry myGeometry = GeometryEngine.Clip(_coloradoGraphic.Geometry, (Envelope)oneGraphic.Geometry); // Only work on returned geometries that are not null. if (myGeometry != null) { // Create the graphic as a result of the clip operation using the same symbology that was defined for // the _coloradoGraphic defined in the Initialize() method previously. Graphic clippedGraphic = new Graphic(myGeometry, _coloradoGraphic.Symbol); // Add the clipped graphic to the clip areas graphics overlay collection. _clipAreasGraphicsOverlay.Graphics.Add(clippedGraphic); } } // Disable the button after has been used. ClipButton.IsEnabled = false; } catch (System.Exception ex) { // Display an error message if there is a problem generating clip operation. var theMessageDialog = new MessageDialog2("Geometry Engine Failed: " + ex.Message); await theMessageDialog.ShowAsync(); } }
private async void Initialize() { try { // Create a new Scene with an imagery basemap. Scene myScene = new Scene(Basemap.CreateImagery()); // Add the Scene to the SceneView. MySceneView.Scene = myScene; // Create a new GraphicsOverlay and add it to the SceneView. GraphicsOverlay graphicsOverlay = new GraphicsOverlay(); graphicsOverlay.SceneProperties.SurfacePlacement = SurfacePlacement.Relative; MySceneView.GraphicsOverlays.Add(graphicsOverlay); // Call a function to create a new distance composite symbol with three ranges. DistanceCompositeSceneSymbol compositeSymbol = await CreateCompositeSymbol(); // Create a new point graphic with the composite symbol, add it to the graphics overlay. MapPoint locationPoint = new MapPoint(-2.708471, 56.096575, 5000, SpatialReferences.Wgs84); Graphic pointGraphic = new Graphic(locationPoint, compositeSymbol); graphicsOverlay.Graphics.Add(pointGraphic); // Add an orbit camera controller to lock the camera to the graphic. OrbitGeoElementCameraController cameraController = new OrbitGeoElementCameraController(pointGraphic, 20) { CameraPitchOffset = 80, CameraHeadingOffset = -30 }; MySceneView.CameraController = cameraController; } catch (Exception e) { var dialog = new MessageDialog2(e.ToString(), "Error"); await dialog.ShowAsync(); } }
/// <summary> /// Method abstracts the platform-specific message box functionality to maximize re-use of common code /// </summary> /// <param name="message">Text of the message to show.</param> private async void ShowStatusMessage(string message) { // Display the message to the user var dialog = new MessageDialog2(message); await dialog.ShowAsync(); }
// Helper function to show a message private async void ShowMessage(string message, string title) { var messageDialog = new MessageDialog2(message, title); await messageDialog.ShowAsync(); }
private async void SaveMapClicked(object sender, RoutedEventArgs e) { try { // Don't attempt to save if the OAuth settings weren't provided if (String.IsNullOrEmpty(_appClientId) || String.IsNullOrEmpty(_oAuthRedirectUrl)) { var dialog = new MessageDialog2("OAuth settings were not provided.", "Cannot Save"); await dialog.ShowAsync(); return; } // Show the progress bar so the user knows work is happening SaveProgressBar.Visibility = Visibility.Visible; // Get the current map Map myMap = MyMapView.Map; // Apply the current extent as the map's initial extent myMap.InitialViewpoint = MyMapView.GetCurrentViewpoint(ViewpointType.BoundingGeometry); // Export the current map view to use as the item's thumbnail RuntimeImage thumbnailImg = await MyMapView.ExportImageAsync(); // See if the map has already been saved (has an associated portal item) if (myMap.Item == null) { // Get information for the new portal item string title = TitleTextBox.Text; string description = DescriptionTextBox.Text; string tagText = TagsTextBox.Text; // Make sure all required info was entered if (String.IsNullOrEmpty(title) || String.IsNullOrEmpty(description) || String.IsNullOrEmpty(tagText)) { throw new Exception("Please enter a title, description, and some tags to describe the map."); } // Call a function to save the map as a new portal item await SaveNewMapAsync(MyMapView.Map, title, description, tagText.Split(','), thumbnailImg); // Report a successful save var messageDialog = new MessageDialog2("Saved '" + title + "' to ArcGIS Online!", "Map Saved"); await messageDialog.ShowAsync(); } else { // This is not the initial save, call SaveAsync to save changes to the existing portal item await myMap.SaveAsync(); // Get the file stream from the new thumbnail image Stream imageStream = await thumbnailImg.GetEncodedBufferAsync(); // Update the item thumbnail ((PortalItem)myMap.Item).SetThumbnail(imageStream); await myMap.SaveAsync(); // Report update was successful var messageDialog = new MessageDialog2("Saved changes to '" + myMap.Item.Title + "'", "Updates Saved"); await messageDialog.ShowAsync(); } } catch (Exception ex) { // Report error message var messageDialog = new MessageDialog2("Error saving map to ArcGIS Online: " + ex.Message); await messageDialog.ShowAsync(); } finally { // Hide the progress bar SaveProgressBar.Visibility = Visibility.Collapsed; } }
private async Task CalculateViewshed(MapPoint location) { // This function will define a new geoprocessing task that performs a custom viewshed analysis based upon a // user click on the map and then display the results back as a polygon fill graphics overlay. If there // is a problem with the execution of the geoprocessing task an error message will be displayed // Create new geoprocessing task using the url defined in the member variables section GeoprocessingTask myViewshedTask = await GeoprocessingTask.CreateAsync(new Uri(_viewshedUrl)); // Create a new feature collection table based upon point geometries using the current map view spatial reference FeatureCollectionTable myInputFeatures = new FeatureCollectionTable(new List <Field>(), GeometryType.Point, MyMapView.SpatialReference); // Create a new feature from the feature collection table. It will not have a coordinate location (x,y) yet Feature myInputFeature = myInputFeatures.CreateFeature(); // Assign a physical location to the new point feature based upon where the user clicked in the map view myInputFeature.Geometry = location; // Add the new feature with (x,y) location to the feature collection table await myInputFeatures.AddFeatureAsync(myInputFeature); // Create the parameters that are passed to the used geoprocessing task GeoprocessingParameters myViewshedParameters = new GeoprocessingParameters(GeoprocessingExecutionType.SynchronousExecute) { // Request the output features to use the same SpatialReference as the map view OutputSpatialReference = MyMapView.SpatialReference }; // Add an input location to the geoprocessing parameters myViewshedParameters.Inputs.Add("Input_Observation_Point", new GeoprocessingFeatures(myInputFeatures)); // Create the job that handles the communication between the application and the geoprocessing task GeoprocessingJob myViewshedJob = myViewshedTask.CreateJob(myViewshedParameters); try { // Execute analysis and wait for the results GeoprocessingResult myAnalysisResult = await myViewshedJob.GetResultAsync(); // Get the results from the outputs GeoprocessingFeatures myViewshedResultFeatures = (GeoprocessingFeatures)myAnalysisResult.Outputs["Viewshed_Result"]; // Add all the results as a graphics to the map IFeatureSet myViewshedAreas = myViewshedResultFeatures.Features; foreach (Feature myFeature in myViewshedAreas) { _resultOverlay.Graphics.Add(new Graphic(myFeature.Geometry)); } } catch (Exception ex) { // Display an error message if there is a problem if (myViewshedJob.Status == JobStatus.Failed && myViewshedJob.Error != null) { var message = new MessageDialog2("Executing geoprocessing failed. " + myViewshedJob.Error.Message, "Geoprocessing error"); await message.ShowAsync(); } else { var message = new MessageDialog2("An error occurred. " + ex, "Sample error"); await message.ShowAsync(); } } finally { // Indicate that the geoprocessing is not running SetBusy(false); } }
private async void QuerySublayers_Click(object sender, RoutedEventArgs e) { // Clear selected features from the graphics overlay. _selectedFeaturesOverlay.Graphics.Clear(); // If the population value entered is not numeric, warn the user and exit. double populationNumber = 0.0; if (!double.TryParse(PopulationTextBox.Text.Trim(), out populationNumber)) { var dialog = new MessageDialog2("The population value must be numeric.", "Query error"); await dialog.ShowAsync(); return; } // Get the USA map image layer (the first and only operational layer in the map). ArcGISMapImageLayer usaMapImageLayer = (ArcGISMapImageLayer)MyMapView.Map.OperationalLayers[0]; try { // Use a utility method on the map image layer to load all the sublayers and tables. await usaMapImageLayer.LoadTablesAndLayersAsync(); // Get the sublayers of interest (skip 'Highways' since it doesn't have the POP2000 field). ArcGISMapImageSublayer citiesSublayer = (ArcGISMapImageSublayer)usaMapImageLayer.Sublayers[0]; ArcGISMapImageSublayer statesSublayer = (ArcGISMapImageSublayer)usaMapImageLayer.Sublayers[2]; ArcGISMapImageSublayer countiesSublayer = (ArcGISMapImageSublayer)usaMapImageLayer.Sublayers[3]; // Get the service feature table for each of the sublayers. ServiceFeatureTable citiesTable = citiesSublayer.Table; ServiceFeatureTable statesTable = statesSublayer.Table; ServiceFeatureTable countiesTable = countiesSublayer.Table; // Create the query parameters that will find features in the current extent with a population greater than the value entered. QueryParameters populationQuery = new QueryParameters { WhereClause = "POP2000 > " + PopulationTextBox.Text, Geometry = MyMapView.GetCurrentViewpoint(ViewpointType.BoundingGeometry).TargetGeometry }; // Query each of the sublayers with the query parameters. FeatureQueryResult citiesQueryResult = await citiesTable.QueryFeaturesAsync(populationQuery); FeatureQueryResult statesQueryResult = await statesTable.QueryFeaturesAsync(populationQuery); FeatureQueryResult countiesQueryResult = await countiesTable.QueryFeaturesAsync(populationQuery); // Display the selected cities in the graphics overlay. SimpleMarkerSymbol citySymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Red, 16); foreach (Feature city in citiesQueryResult) { Graphic cityGraphic = new Graphic(city.Geometry, citySymbol); _selectedFeaturesOverlay.Graphics.Add(cityGraphic); } // Display the selected counties in the graphics overlay. SimpleLineSymbol countyLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Dash, Color.Cyan, 2); SimpleFillSymbol countySymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.DiagonalCross, Color.Cyan, countyLineSymbol); foreach (Feature county in countiesQueryResult) { Graphic countyGraphic = new Graphic(county.Geometry, countySymbol); _selectedFeaturesOverlay.Graphics.Add(countyGraphic); } // Display the selected states in the graphics overlay. SimpleLineSymbol stateLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.DarkCyan, 6); SimpleFillSymbol stateSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.Null, Color.Cyan, stateLineSymbol); foreach (Feature state in statesQueryResult) { Graphic stateGraphic = new Graphic(state.Geometry, stateSymbol); _selectedFeaturesOverlay.Graphics.Add(stateGraphic); } } catch (Exception ex) { await new MessageDialog2(ex.ToString(), "Error").ShowAsync(); } }
private async void OnAnalyzeHotspotsClicked(object sender, RoutedEventArgs e) { // Clear any existing results MyMapView.Map.OperationalLayers.Clear(); // Show the BusyOverlay indication ShowBusyOverlay(); // Get the 'from' and 'to' dates from the date pickers for the geoprocessing analysis DateTimeOffset myFromDate = FromDate.Date; DateTimeOffset myToDate = ToDate.Date; // The end date must be at least one day after the start date if (myToDate <= myFromDate.AddDays(1)) { // Show error message var message = new MessageDialog2("Please select valid time range. There has to be at least one day in between To and From dates.", "Invalid date range"); await message.ShowAsync(); // Remove the BusyOverlay ShowBusyOverlay(false); return; } // Create the parameters that are passed to the used geoprocessing task GeoprocessingParameters myHotspotParameters = new GeoprocessingParameters(GeoprocessingExecutionType.AsynchronousSubmit); // Construct the date query string myQueryString = $"(\"DATE\" > date '{myFromDate:yyyy-MM-dd} 00:00:00' AND \"DATE\" < date '{myToDate:yyyy-MM-dd} 00:00:00')"; // Add the query that contains the date range used in the analysis myHotspotParameters.Inputs.Add("Query", new GeoprocessingString(myQueryString)); // Create job that handles the communication between the application and the geoprocessing task _hotspotJob = _hotspotTask.CreateJob(myHotspotParameters); try { // Execute the geoprocessing analysis and wait for the results GeoprocessingResult myAnalysisResult = await _hotspotJob.GetResultAsync(); // Add results to a map using map server from a geoprocessing task // Load to get access to full extent await myAnalysisResult.MapImageLayer.LoadAsync(); // Add the analysis layer to the map view MyMapView.Map.OperationalLayers.Add(myAnalysisResult.MapImageLayer); // Zoom to the results await MyMapView.SetViewpointAsync(new Viewpoint(myAnalysisResult.MapImageLayer.FullExtent)); } catch (TaskCanceledException) { // This is thrown if the task is canceled. Ignore. } catch (Exception ex) { // Display error messages if the geoprocessing task fails if (_hotspotJob.Status == JobStatus.Failed && _hotspotJob.Error != null) { var message = new MessageDialog2("Executing geoprocessing failed. " + _hotspotJob.Error.Message, "Geoprocessing error"); await message.ShowAsync(); } else { var message = new MessageDialog2("An error occurred. " + ex.ToString(), "Sample error"); await message.ShowAsync(); } } finally { // Remove the BusyOverlay ShowBusyOverlay(false); } }
// Handle a new selected comment record in the table view. private async void CommentsListBox_SelectionChanged(object sender, Microsoft.UI.Xaml.Controls.SelectionChangedEventArgs e) { // Clear selected features from the graphics overlay. _selectedFeaturesOverlay.Graphics.Clear(); // Get the selected comment feature. If there is no selection, return. ArcGISFeature selectedComment = e.AddedItems[0] as ArcGISFeature; if (selectedComment == null) { return; } // Get the map image layer that contains the service request sublayer and the service request comments table. ArcGISMapImageLayer serviceRequestsMapImageLayer = (ArcGISMapImageLayer)MyMapView.Map.OperationalLayers[0]; // Get the (non-spatial) table that contains the service request comments. ServiceFeatureTable commentsTable = serviceRequestsMapImageLayer.Tables[0]; // Get the relationship that defines related service request features for features in the comments table (this is the first and only relationship). RelationshipInfo commentsRelationshipInfo = commentsTable.LayerInfo.RelationshipInfos.FirstOrDefault(); // Create query parameters to get the related service request for features in the comments table. RelatedQueryParameters relatedQueryParams = new RelatedQueryParameters(commentsRelationshipInfo) { ReturnGeometry = true }; try { // Query the comments table to get the related service request feature for the selected comment. IReadOnlyList <RelatedFeatureQueryResult> relatedRequestsResult = await commentsTable.QueryRelatedFeaturesAsync(selectedComment, relatedQueryParams); // Get the first result. RelatedFeatureQueryResult result = relatedRequestsResult.FirstOrDefault(); // Get the first feature from the result. If it's null, warn the user and return. ArcGISFeature serviceRequestFeature = result.FirstOrDefault() as ArcGISFeature; if (serviceRequestFeature == null) { var message = new MessageDialog2("Related feature not found.", "No Feature"); await message.ShowAsync(); return; } // Load the related service request feature (so its geometry is available). await serviceRequestFeature.LoadAsync(); // Get the service request geometry (point). MapPoint serviceRequestPoint = serviceRequestFeature.Geometry as MapPoint; // Create a cyan marker symbol to display the related feature. Symbol selectedRequestSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Cyan, 14); // Create a graphic using the service request point and marker symbol. Graphic requestGraphic = new Graphic(serviceRequestPoint, selectedRequestSymbol); // Add the graphic to the graphics overlay and zoom the map view to its extent. _selectedFeaturesOverlay.Graphics.Add(requestGraphic); await MyMapView.SetViewpointCenterAsync(serviceRequestPoint, 150000); } catch (Exception ex) { await new MessageDialog2(ex.ToString(), "Error").ShowAsync(); } }
// Note: all code below (except call to ConfigureOfflineJobForBasemap) is identical to code in the Generate offline map sample. #region Generate offline map private async void Initialize() { try { // Call a function to set up the AuthenticationManager for OAuth. SetOAuthInfo(); // Create the ArcGIS Online portal. ArcGISPortal portal = await ArcGISPortal.CreateAsync(); // Get the Naperville water web map item using its ID. PortalItem webmapItem = await PortalItem.CreateAsync(portal, WebMapId); // Create a map from the web map item. Map onlineMap = new Map(webmapItem); // Display the map in the MapView. MyMapView.Map = onlineMap; // Disable user interactions on the map (no panning or zooming from the initial extent). MyMapView.InteractionOptions = new MapViewInteractionOptions { IsEnabled = false }; // Create a graphics overlay for the extent graphic and apply a renderer. SimpleLineSymbol aoiOutlineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, System.Drawing.Color.Red, 3); GraphicsOverlay extentOverlay = new GraphicsOverlay { Renderer = new SimpleRenderer(aoiOutlineSymbol) }; MyMapView.GraphicsOverlays.Add(extentOverlay); // Add a graphic to show the area of interest (extent) that will be taken offline. Graphic aoiGraphic = new Graphic(_areaOfInterest); extentOverlay.Graphics.Add(aoiGraphic); // Hide the map loading progress indicator. LoadingIndicator.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed; // When the map view unloads, try to clean up existing output data folders. MyMapView.Unloaded += (s, e) => { // Find output mobile map folders in the temp directory. string[] outputFolders = Directory.GetDirectories(Environment.ExpandEnvironmentVariables("%TEMP%"), "NapervilleWaterNetwork*"); // Loop through the folder names and delete them. foreach (string dir in outputFolders) { try { // Delete the folder. Directory.Delete(dir, true); } catch (Exception) { // Ignore exceptions (files might be locked, for example). } } }; } catch (Exception ex) { var dialog = new MessageDialog2(ex.ToString(), "Error loading map"); await dialog.ShowAsync(); } }
private async Task <MultilayerPointSymbol> GetCurrentSymbol() { // If the style hasn't been opened, return. if (_emojiStyle == null) { return(null); } MultilayerPointSymbol faceSymbol = null; try { // Get the key that identifies the selected eye symbol (or an empty string if none selected). SymbolLayerInfo eyeLayerInfo = (SymbolLayerInfo)EyeSymbolList.SelectedItem; string eyeLayerKey = eyeLayerInfo != null ? eyeLayerInfo.Key : string.Empty; // Get the key that identifies the selected mouth symbol (or an empty string if none selected). SymbolLayerInfo mouthLayerInfo = (SymbolLayerInfo)MouthSymbolList.SelectedItem; string mouthLayerKey = mouthLayerInfo != null ? mouthLayerInfo.Key : string.Empty; // Get the key that identifies the selected hat symbol (or an empty string if none selected). SymbolLayerInfo hatLayerInfo = (SymbolLayerInfo)HatSymbolList.SelectedItem; string hatLayerKey = hatLayerInfo != null ? hatLayerInfo.Key : string.Empty; // Create a list of the symbol keys that identify the selected symbol layers, including the base (circle) symbol. List <string> symbolKeys = new List <string> { _baseSymbolKey, eyeLayerKey, mouthLayerKey, hatLayerKey }; // Get a multilayer point symbol from the style that contains the selected symbol layers. faceSymbol = await _emojiStyle.GetSymbolAsync(symbolKeys) as MultilayerPointSymbol; // Loop through all symbol layers and lock the color. foreach (SymbolLayer lyr in faceSymbol.SymbolLayers) { // Changing the color of the symbol will not affect this layer. lyr.IsColorLocked = true; } // Unlock the color for the base (first) layer. Changing the symbol color will change this layer's color. faceSymbol.SymbolLayers.First().IsColorLocked = false; // Set the symbol color from the combo box. if (FaceColorComboBox.SelectedItem != null) { faceSymbol.Color = (Color)FaceColorComboBox.SelectedItem; } // Set the symbol size from the slider. faceSymbol.Size = SizeSlider.Value; } catch (Exception ex) { // Report the exception. var dialog = new MessageDialog2("Error creating the symbol: " + ex.Message); await dialog.ShowAsync(); } // Return the multilayer point symbol. return(faceSymbol); }
private async Task ReadMobileStyle(string stylePath) { try { // Open the mobile style file at the provided path. _emojiStyle = await SymbolStyle.OpenAsync(stylePath); // Get the default style search parameters. SymbolStyleSearchParameters searchParams = await _emojiStyle.GetDefaultSearchParametersAsync(); // Search the style with the default parameters to return all symbol results. IList <SymbolStyleSearchResult> styleResults = await _emojiStyle.SearchSymbolsAsync(searchParams); // Create an empty placeholder image to represent "no symbol" for each category. ImageSource emptyImage = null; // Create lists to contain the available symbol layers for each category of symbol and add an empty entry as default. List <SymbolLayerInfo> eyeSymbolInfos = new List <SymbolLayerInfo> { new SymbolLayerInfo("", emptyImage, "") }; List <SymbolLayerInfo> mouthSymbolInfos = new List <SymbolLayerInfo> { new SymbolLayerInfo("", emptyImage, "") }; List <SymbolLayerInfo> hatSymbolInfos = new List <SymbolLayerInfo>() { new SymbolLayerInfo("", emptyImage, "") }; // Loop through the results and put symbols into the appropriate list according to category. foreach (SymbolStyleSearchResult result in styleResults) { // Get the symbol for this result. MultilayerPointSymbol multiLayerSym = await result.GetSymbolAsync() as MultilayerPointSymbol; // Create a swatch image from the symbol. RuntimeImage swatch = await multiLayerSym.CreateSwatchAsync(); ImageSource symbolImage = await swatch.ToImageSourceAsync(); // Create a symbol layer info object to represent the symbol in the list. // The symbol key will be used to retrieve the symbol from the style. SymbolLayerInfo symbolInfo = new SymbolLayerInfo(result.Name, symbolImage, result.Key); // Add the symbol layer info to the correct list for its category. switch (result.Category) { case "Eyes": { eyeSymbolInfos.Add(symbolInfo); break; } case "Mouth": { mouthSymbolInfos.Add(symbolInfo); break; } case "Hat": { hatSymbolInfos.Add(symbolInfo); break; } } } // Show the symbols in the category list boxes. EyeSymbolList.ItemsSource = eyeSymbolInfos; MouthSymbolList.ItemsSource = mouthSymbolInfos; HatSymbolList.ItemsSource = hatSymbolInfos; // Call a function to construct the current symbol (default yellow circle). Symbol faceSymbol = await GetCurrentSymbol(); // Call a function to show a preview image of the symbol. await UpdateSymbolPreview(faceSymbol); } catch (Exception ex) { // Report the exception. var dialog = new MessageDialog2("Error reading symbols from style: " + ex.Message); await dialog.ShowAsync(); } }
private async void AddMapItemClick(object sender, RoutedEventArgs e) { // Get a web map from the selected portal item and display it in the map view. if (MapItemListBox.SelectedItem == null) { var dialog = new MessageDialog2("No web map item is selected."); await dialog.ShowAsync(); return; } // Clear status messages. MessagesTextBlock.Text = string.Empty; // Store status (or errors) when adding the map. var statusInfo = new StringBuilder(); try { // Clear the current MapView control from the app. MyMapGrid.Children.Clear(); // See if using the public or secured portal; get the appropriate object reference. ArcGISPortal portal = null; if (_usingPublicPortal) { portal = _publicPortal; } else { portal = _iwaSecuredPortal; } // Throw an exception if the portal is null. if (portal == null) { throw new Exception("Portal has not been instantiated."); } // Get the portal item ID from the selected list box item (read it from the Tag property). var itemId = (MapItemListBox.SelectedItem as ListBoxItem).Tag.ToString(); // Use the item ID to create a PortalItem from the appropriate portal. var portalItem = await PortalItem.CreateAsync(portal, itemId); if (portalItem != null) { // Create a Map using the web map (portal item). Map webMap = new Map(portalItem); // Create a new MapView control to display the Map. MapView myMapView = new MapView { Map = webMap }; // Add the MapView to the app. MyMapGrid.Children.Add(myMapView); } // Report success. statusInfo.AppendLine("Successfully loaded web map from item #" + itemId + " from " + portal.Uri.Host); } catch (Exception ex) { // Add an error message. statusInfo.AppendLine("Error accessing web map: " + ex.Message); } finally { // Show messages. MessagesTextBlock.Text = statusInfo.ToString(); } }
private async void TakeMapOfflineButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { // Create a new folder for the output mobile map. string packagePath = Path.Combine(Environment.ExpandEnvironmentVariables("%TEMP%"), @"NapervilleWaterNetwork"); int num = 1; while (Directory.Exists(packagePath)) { packagePath = Path.Combine(Environment.ExpandEnvironmentVariables("%TEMP%"), @"NapervilleWaterNetwork" + num.ToString()); num++; } // Create the output directory. Directory.CreateDirectory(packagePath); try { // Show the progress indicator while the job is running. BusyIndicator.Visibility = Microsoft.UI.Xaml.Visibility.Visible; // Create an offline map task with the current (online) map. OfflineMapTask takeMapOfflineTask = await OfflineMapTask.CreateAsync(MyMapView.Map); // Create the default parameters for the task, pass in the area of interest. GenerateOfflineMapParameters parameters = await takeMapOfflineTask.CreateDefaultGenerateOfflineMapParametersAsync(_areaOfInterest); // Configure basemap settings for the job. await ConfigureOfflineJobForBasemap(parameters); // Create the job with the parameters and output location. _generateOfflineMapJob = takeMapOfflineTask.GenerateOfflineMap(parameters, packagePath); // Handle the progress changed event for the job. _generateOfflineMapJob.ProgressChanged += OfflineMapJob_ProgressChanged; // Await the job to generate geodatabases, export tile packages, and create the mobile map package. GenerateOfflineMapResult results = await _generateOfflineMapJob.GetResultAsync(); // Check for job failure (writing the output was denied, e.g.). if (_generateOfflineMapJob.Status != JobStatus.Succeeded) { var dialog = new MessageDialog2("Generate offline map package failed.", "Job status"); await dialog.ShowAsync(); BusyIndicator.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed; } // Check for errors with individual layers. if (results.LayerErrors.Any()) { // Build a string to show all layer errors. System.Text.StringBuilder errorBuilder = new System.Text.StringBuilder(); foreach (KeyValuePair <Layer, Exception> layerError in results.LayerErrors) { errorBuilder.AppendLine($"{layerError.Key.Id} : {layerError.Value.Message}"); } // Show layer errors. string errorText = errorBuilder.ToString(); var dialog = new MessageDialog2(errorText, "Layer errors"); await dialog.ShowAsync(); } // Display the offline map. MyMapView.Map = results.OfflineMap; // Apply the original viewpoint for the offline map. MyMapView.SetViewpoint(new Viewpoint(_areaOfInterest)); // Enable map interaction so the user can explore the offline data. MyMapView.InteractionOptions.IsEnabled = true; // Hide the "Take map offline" button. TakeOfflineArea.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed; // Show a message that the map is offline. MessageArea.Visibility = Microsoft.UI.Xaml.Visibility.Visible; } catch (TaskCanceledException) { // Generate offline map task was canceled. var dialog = new MessageDialog2("Taking map offline was canceled"); await dialog.ShowAsync(); } catch (Exception ex) { // Exception while taking the map offline. var dialog = new MessageDialog2(ex.Message, "Offline map error"); await dialog.ShowAsync(); } finally { // Hide the activity indicator when the job is done. BusyIndicator.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed; } }