From aecdc7fee142d6543c4fe9d19054f5903ff9ffad Mon Sep 17 00:00:00 2001 From: Hamish Duff Date: Tue, 1 Aug 2023 15:10:05 +0100 Subject: [PATCH] implement WinUI and MAUI --- .../GeodatabaseTransactions.xaml.cs | 196 ++++++++++-------- .../Data/GeodatabaseTransactions/readme.md | 3 +- .../readme.metadata.json | 4 +- .../CreateAndSaveKmlFile.xaml.cs | 87 ++++---- .../Layers/CreateAndSaveKmlFile/readme.md | 6 +- .../CreateAndSaveKmlFile/readme.metadata.json | 7 +- .../FindServiceArea/FindServiceArea.xaml.cs | 131 +++++++----- .../NetworkAnalysis/FindServiceArea/readme.md | 2 +- .../FindServiceArea/readme.metadata.json | 1 + .../GeodatabaseTransactions.xaml.cs | 6 +- .../readme.metadata.json | 4 +- .../CreateAndSaveKmlFile.xaml.cs | 21 +- .../CreateAndSaveKmlFile/readme.metadata.json | 7 +- .../FindServiceArea/FindServiceArea.xaml.cs | 18 +- .../FindServiceArea/readme.metadata.json | 1 + .../GeodatabaseTransactions.xaml.cs | 196 ++++++++++-------- .../Data/GeodatabaseTransactions/readme.md | 3 +- .../readme.metadata.json | 4 +- .../CreateAndSaveKmlFile.xaml.cs | 88 ++++---- .../Layers/CreateAndSaveKmlFile/readme.md | 6 +- .../CreateAndSaveKmlFile/readme.metadata.json | 7 +- .../FindServiceArea/FindServiceArea.xaml.cs | 124 ++++++----- .../NetworkAnalysis/FindServiceArea/readme.md | 2 +- .../FindServiceArea/readme.metadata.json | 1 + 24 files changed, 517 insertions(+), 408 deletions(-) diff --git a/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs b/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs index 4bd845b783..8700b32de1 100644 --- a/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs +++ b/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs @@ -21,63 +21,66 @@ namespace ArcGIS.Samples.GeodatabaseTransactions category: "Data", description: "Use transactions to manage how changes are committed to a geodatabase.", instructions: "When the sample loads, a feature service is taken offline as a geodatabase. When the geodatabase is ready, you can add multiple types of features. To apply edits directly, uncheck the 'Require a transaction for edits' checkbox. When using transactions, use the buttons to start editing and stop editing. When you stop editing, you can choose to commit the changes or roll them back. At any point, you can synchronize the local geodatabase with the feature service.", - tags: new[] { "commit", "database", "geodatabase", "transact", "transactions" })] + tags: new[] { "commit", "database", "geodatabase", "geometry editor", "transact", "transactions" })] public partial class GeodatabaseTransactions : ContentPage { - // URL for the editable feature service + // URL for the editable feature service. private const string SyncServiceUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/SaveTheBaySync/FeatureServer/"; - // Work in a small extent south of Galveston, TX + // Work in a small extent south of Galveston, TX. private Envelope _extent = new Envelope(-95.3035, 29.0100, -95.1053, 29.1298, SpatialReferences.Wgs84); - // Store the local geodatabase to edit + // Store the local geodatabase to edit. private Geodatabase _localGeodatabase; - // Store references to two tables to edit: Birds and Marine points + // Store references to two tables to edit: Birds and Marine points. private GeodatabaseFeatureTable _birdTable; private GeodatabaseFeatureTable _marineTable; + // Store a reference to the table to be edited. + private GeodatabaseFeatureTable _editTable; + public GeodatabaseTransactions() { InitializeComponent(); - // When the spatial reference changes (the map loads) add the local geodatabase tables as feature layers + // When the spatial reference changes (the map loads) add the local geodatabase tables as feature layers. MyMapView.SpatialReferenceChanged += async (s, e) => { - // Call a function (and await it) to get the local geodatabase (or generate it from the feature service) + // Call a function (and await it) to get the local geodatabase (or generate it from the feature service). await GetLocalGeodatabase(); - // Once the local geodatabase is available, load the tables as layers to the map + // Once the local geodatabase is available, load the tables as layers to the map. await LoadLocalGeodatabaseTables(); }; - // Create a new map with the oceans basemap and add it to the map view + // Create a new map with the oceans basemap and add it to the map view. Map map = new Map(BasemapStyle.ArcGISOceans); MyMapView.Map = map; } private async Task GetLocalGeodatabase() { - // Get the path to the local geodatabase for this platform (temp directory, for example) + // Get the path to the local geodatabase for this platform (temp directory, for example). string localGeodatabasePath = GetGdbPath(); try { - // See if the geodatabase file is already present + // See if the geodatabase file is already present. if (File.Exists(localGeodatabasePath)) { - // If the geodatabase is already available, open it, hide the progress control, and update the message + // If the geodatabase is already available, open it, hide the progress control, and update the message. _localGeodatabase = await Geodatabase.OpenAsync(localGeodatabasePath); LoadingProgressBar.IsVisible = false; MessageTextBlock.Text = "Using local geodatabase from '" + _localGeodatabase.Path + "'"; } else { - // Create a new GeodatabaseSyncTask with the uri of the feature server to pull from + // Create a new GeodatabaseSyncTask with the uri of the feature server to pull from. Uri uri = new Uri(SyncServiceUrl); GeodatabaseSyncTask gdbTask = await GeodatabaseSyncTask.CreateAsync(uri); - // Create parameters for the task: layers and extent to include, out spatial reference, and sync model + // Create parameters for the task: layers and extent to include, out spatial reference, and sync model. GenerateGeodatabaseParameters gdbParams = await gdbTask.CreateDefaultGenerateGeodatabaseParametersAsync(_extent); gdbParams.OutSpatialReference = MyMapView.SpatialReference; gdbParams.SyncModel = SyncModel.Layer; @@ -85,18 +88,18 @@ private async Task GetLocalGeodatabase() gdbParams.LayerOptions.Add(new GenerateLayerOption(0)); gdbParams.LayerOptions.Add(new GenerateLayerOption(1)); - // Create a geodatabase job that generates the geodatabase + // Create a geodatabase job that generates the geodatabase. GenerateGeodatabaseJob generateGdbJob = gdbTask.GenerateGeodatabase(gdbParams, localGeodatabasePath); - // Handle the job changed event and check the status of the job; store the geodatabase when it's ready + // Handle the job changed event and check the status of the job; store the geodatabase when it's ready. generateGdbJob.StatusChanged += (s, e) => { - // See if the job succeeded + // See if the job succeeded. if (generateGdbJob.Status == JobStatus.Succeeded) { Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(() => { - // Hide the progress control and update the message + // Hide the progress control and update the message. LoadingProgressBar.IsVisible = false; MessageTextBlock.Text = "Created local geodatabase"; }); @@ -105,20 +108,20 @@ private async Task GetLocalGeodatabase() { Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(() => { - // Hide the progress control and report the exception + // Hide the progress control and report the exception. LoadingProgressBar.IsVisible = false; MessageTextBlock.Text = "Unable to create local geodatabase: " + generateGdbJob.Error.Message; }); } }; - // Start the generate geodatabase job + // Start the generate geodatabase job. _localGeodatabase = await generateGdbJob.GetResultAsync(); } } catch (Exception ex) { - // Show a message for the exception encountered + // Show a message for the exception encountered. Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(() => { Application.Current.MainPage.DisplayAlert("Generate Geodatabase", "Unable to create offline database: " + ex.Message, "OK"); @@ -126,32 +129,32 @@ private async Task GetLocalGeodatabase() } } - // Function that loads the two point tables from the local geodatabase and displays them as feature layers + // Function that loads the two point tables from the local geodatabase and displays them as feature layers. private async Task LoadLocalGeodatabaseTables() { if (_localGeodatabase == null) { return; } - // Read the geodatabase tables and add them as layers + // Read the geodatabase tables and add them as layers. foreach (GeodatabaseFeatureTable table in _localGeodatabase.GeodatabaseFeatureTables) { try { - // Load the table so the TableName can be read + // Load the table so the TableName can be read. await table.LoadAsync(); - // Store a reference to the Birds table + // Store a reference to the Birds table. if (table.TableName.ToLower().Contains("birds")) { _birdTable = table; } - // Store a reference to the Marine table + // Store a reference to the Marine table. if (table.TableName.ToLower().Contains("marine")) { _marineTable = table; } - // Create a new feature layer to show the table in the map + // Create a new feature layer to show the table in the map. FeatureLayer layer = new FeatureLayer(table); Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(() => MyMapView.Map.OperationalLayers.Add(layer)); } @@ -161,10 +164,10 @@ private async Task LoadLocalGeodatabaseTables() } } - // Handle the transaction status changed event + // Handle the transaction status changed event. _localGeodatabase.TransactionStatusChanged += GdbTransactionStatusChanged; - // Zoom the map view to the extent of the generated local datasets + // Zoom the map view to the extent of the generated local datasets. Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(() => { MyMapView.SetViewpoint(new Viewpoint(_marineTable.Extent)); @@ -175,15 +178,15 @@ private async Task LoadLocalGeodatabaseTables() private void GdbTransactionStatusChanged(object sender, TransactionStatusChangedEventArgs e) { - // Update UI controls based on whether the geodatabase has a current transaction + // Update UI controls based on whether the geodatabase has a current transaction. Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread(() => { - // These buttons should be enabled when there IS a transaction + // These buttons should be enabled when there IS a transaction. AddBirdButton.IsEnabled = e.IsInTransaction; AddMarineButton.IsEnabled = e.IsInTransaction; StopEditingButton.IsEnabled = e.IsInTransaction; - // These buttons should be enabled when there is NOT a transaction + // These buttons should be enabled when there is NOT a transaction. StartEditingButton.IsEnabled = !e.IsInTransaction; SyncEditsButton.IsEnabled = !e.IsInTransaction; RequireTransactionCheckBox.IsEnabled = !e.IsInTransaction; @@ -192,116 +195,133 @@ private void GdbTransactionStatusChanged(object sender, TransactionStatusChanged private string GetGdbPath() { - // Set the platform-specific path for storing the geodatabase + // Set the platform-specific path for storing the geodatabase. string folder = string.Empty; #if WINDOWS folder = Windows.Storage.ApplicationData.Current.LocalFolder.Path; #elif IOS || ANDROID folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); #endif - // Set the final path + // Set the final path. return Path.Combine(folder, "savethebay.geodatabase"); } private void BeginTransaction(object sender, EventArgs e) { - // See if there is a transaction active for the geodatabase + // See if there is a transaction active for the geodatabase. if (!_localGeodatabase.IsInTransaction) { - // If not, begin a transaction + // If not, begin a transaction. _localGeodatabase.BeginTransaction(); MessageTextBlock.Text = "Transaction started"; } } - private async void AddNewFeature(object sender, EventArgs args) + private void AddNewFeature(object sender, EventArgs args) { - // See if it was the "Birds" or "Marine" button that was clicked + // See if it was the "Birds" or "Marine" button that was clicked. Button addFeatureButton = (Button)sender; try { - // Cancel execution of the sketch task if it is already active - if (MyMapView.SketchEditor.CancelCommand.CanExecute(null)) + // Cancel execution of the sketch task if it is already active. + if (MyMapView.GeometryEditor.IsStarted) { - MyMapView.SketchEditor.CancelCommand.Execute(null); + MyMapView.GeometryEditor.Stop(); } - // Store the correct table to edit (for the button clicked) - GeodatabaseFeatureTable editTable = null; + // Store the correct table to edit (for the button clicked). if (addFeatureButton == AddBirdButton) { - editTable = _birdTable; + _editTable = _birdTable; } else { - editTable = _marineTable; + _editTable = _marineTable; } - // Inform the user which table is being edited - MessageTextBlock.Text = "Click the map to add a new feature to the geodatabase table '" + editTable.TableName + "'"; - - // Create a random value for the 'type' attribute (integer between 1 and 7) - Random random = new Random(DateTime.Now.Millisecond); - int featureType = random.Next(1, 7); - - // Use the sketch editor to allow the user to draw a point on the map - MapPoint clickPoint = await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Point, false) as MapPoint; - - // Create a new feature (row) in the selected table - Feature newFeature = editTable.CreateFeature(); + // Inform the user which table is being edited. + MessageTextBlock.Text = "Click the map to add a new feature to the geodatabase table '" + _editTable.TableName + "'"; - // Set the geometry with the point the user clicked and the 'type' with the random integer - newFeature.Geometry = clickPoint; - newFeature.SetAttributeValue("type", featureType); - - // Add the new feature to the table - await editTable.AddFeatureAsync(newFeature); + // Use the geometry editor to allow the user to draw a point on the map. + MyMapView.GeometryEditor.Start(GeometryType.Point); - // Clear the message - MessageTextBlock.Text = "New feature added to the '" + editTable.TableName + "' table"; + MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; } catch (TaskCanceledException) { - // Ignore if the edit was canceled + // Ignore if the edit was canceled. } catch (Exception ex) { - // Report other exception messages + // Report other exception messages. MessageTextBlock.Text = ex.Message; } } + private async void GeometryEditor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + // Check if the user finished drawing a point on the map. + if (e.PropertyName == "Geometry") + { + // Disconnect event handler to prevent multiple calls. + MyMapView.GeometryEditor.PropertyChanged -= GeometryEditor_PropertyChanged; + + // Get the active geometry. + Geometry geometry = MyMapView.GeometryEditor.Geometry; + + // Create a new feature (row) in the selected table. + Feature newFeature = _editTable.CreateFeature(); + + // Create a random value for the 'type' attribute (integer between 1 and 7). + Random random = new Random(DateTime.Now.Millisecond); + int featureType = random.Next(1, 7); + + // Set the geometry with the point the user clicked and the 'type' with the random integer. + newFeature.Geometry = geometry; + newFeature.SetAttributeValue("type", featureType); + + // Add the new feature to the table. + await _editTable.AddFeatureAsync(newFeature); + + // Set the newly created feature message. + MessageTextBlock.Text = "New feature added to the '" + _editTable.TableName + "' table"; + + // Stop the geometry editor, clearing the active geometry. + MyMapView.GeometryEditor.Stop(); + } + } + private async void StopEditTransaction(object sender, EventArgs e) { try { - // Ask the user if they want to commit or rollback the transaction (or cancel to keep working in the transaction) + // Ask the user if they want to commit or rollback the transaction (or cancel to keep working in the transaction). string choice = await Application.Current.MainPage.DisplayActionSheet("Transaction", "Cancel", null, "Commit", "Rollback"); if (choice == "Commit") { - // See if there is a transaction active for the geodatabase + // 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) + // 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 (choice == "Rollback") { - // See if there is a transaction active for the geodatabase + // 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) + // 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 + // For 'cancel' don't end the transaction with a commit or rollback. } } catch (Exception ex) @@ -310,16 +330,16 @@ private async void StopEditTransaction(object sender, EventArgs e) } } - // Change which controls are enabled if the user chooses to require/not require transactions for edits + // Change which controls are enabled if the user chooses to require/not require transactions for edits. private void RequireTransactionChanged(object sender, EventArgs e) { - // If the local geodatabase isn't created yet, return + // If the local geodatabase isn't created yet, return. if (_localGeodatabase == null) { return; } - // Get the value of the "require transactions" checkbox + // Get the value of the "require transactions" checkbox. bool mustHaveTransaction = RequireTransactionCheckBox.IsToggled; - // Warn the user if disabling transactions while a transaction is active + // Warn the user if disabling transactions while a transaction is active. if (!mustHaveTransaction && _localGeodatabase.IsInTransaction) { Application.Current.MainPage.DisplayAlert("Stop editing to end the current transaction.", "Current Transaction", "OK"); @@ -327,34 +347,34 @@ private void RequireTransactionChanged(object sender, EventArgs e) return; } - // Enable or disable controls according to the checkbox value + // Enable or disable controls according to the checkbox value. StartEditingButton.IsEnabled = mustHaveTransaction; StopEditingButton.IsEnabled = mustHaveTransaction && _localGeodatabase.IsInTransaction; AddBirdButton.IsEnabled = !mustHaveTransaction; AddMarineButton.IsEnabled = !mustHaveTransaction; } - // Synchronize edits in the local geodatabase with the service + // Synchronize edits in the local geodatabase with the service. public async void SynchronizeEdits(object sender, EventArgs e) { - // Show the progress bar while the sync is working + // Show the progress bar while the sync is working. LoadingProgressBar.IsVisible = true; try { - // Create a sync task with the URL of the feature service to sync + // Create a sync task with the URL of the feature service to sync. GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(SyncServiceUrl)); - // Create sync parameters + // Create sync parameters. SyncGeodatabaseParameters taskParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(_localGeodatabase); - // Create a synchronize geodatabase job, pass in the parameters and the geodatabase + // Create a synchronize geodatabase job, pass in the parameters and the geodatabase. SyncGeodatabaseJob job = syncTask.SyncGeodatabase(taskParameters, _localGeodatabase); - // Handle the JobChanged event for the job + // Handle the JobChanged event for the job. job.StatusChanged += (s, arg) => { - // Report changes in the job status + // Report changes in the job status. if (job.Status == JobStatus.Succeeded) { // Report success ... @@ -372,17 +392,17 @@ public async void SynchronizeEdits(object sender, EventArgs e) } }; - // Await the completion of the job + // Await the completion of the job. await job.GetResultAsync(); } catch (Exception ex) { - // Show the message if an exception occurred + // Show the message if an exception occurred. MessageTextBlock.Text = "Error when synchronizing: " + ex.Message; } finally { - // Hide the progress bar when the sync job is complete + // Hide the progress bar when the sync job is complete. LoadingProgressBar.IsVisible = false; } } diff --git a/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.md b/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.md index f3c805d2ea..c3ad7717ce 100644 --- a/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.md +++ b/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.md @@ -27,6 +27,7 @@ When the sample loads, a feature service is taken offline as a geodatabase. When * Geodatabase.CommitTransaction * Geodatabase.IsInTransaction * Geodatabase.RollbackTransaction +* GeometryEditor ## About the data @@ -34,4 +35,4 @@ The sample uses a publicly-editable, sync-enabled [feature service](https://samp ## Tags -commit, database, geodatabase, transact, transactions \ No newline at end of file +commit, database, geodatabase, geometry editor, transact, transactions \ No newline at end of file diff --git a/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.metadata.json b/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.metadata.json index 6bd8737def..07bc56e915 100644 --- a/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.metadata.json +++ b/src/MAUI/Maui.Samples/Samples/Data/GeodatabaseTransactions/readme.metadata.json @@ -10,6 +10,7 @@ "commit", "database", "geodatabase", + "geometry editor", "transact", "transactions" ], @@ -22,7 +23,8 @@ "Geodatabase.BeginTransaction", "Geodatabase.CommitTransaction", "Geodatabase.IsInTransaction", - "Geodatabase.RollbackTransaction" + "Geodatabase.RollbackTransaction", + "GeometryEditor" ], "snippets": [ "GeodatabaseTransactions.xaml.cs", diff --git a/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs b/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs index 8d113054ad..8ecb7b49fa 100644 --- a/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs +++ b/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs @@ -29,7 +29,7 @@ namespace ArcGIS.Samples.CreateAndSaveKmlFile category: "Layers", description: "Construct a KML document and save it as a KMZ file.", instructions: "Tap on one of the buttons in the middle row to start adding a geometry. Tap on the map view to place vertices. Tap the \"Complete Sketch\" button to add the geometry to the KML document as a new KML placemark. Use the style interface to edit the style of the placemark. If you do not wish to set a style, tap the \"Don't Apply Style\" button. When you are finished adding KML nodes, tap on the \"Save KMZ file\" button to save the active KML document as a .kmz file on your system. Use the \"Reset\" button to clear the current KML document and start a new one.", - tags: new[] { "KML", "KMZ", "Keyhole", "OGC" })] + tags: new[] { "KML", "KMZ", "Keyhole", "OGC", "geometry editor" })] [ArcGIS.Samples.Shared.Attributes.OfflineData()] [ArcGIS.Samples.Shared.Attributes.ClassFile("Converters/ImageConverter.cs", "Converters/ColorConverter.cs")] public partial class CreateAndSaveKmlFile : ContentPage @@ -38,6 +38,7 @@ public partial class CreateAndSaveKmlFile : ContentPage private KmlDataset _kmlDataset; private KmlLayer _kmlLayer; private KmlPlacemark _currentPlacemark; + private GeometryType _geometryType; public CreateAndSaveKmlFile() { @@ -103,24 +104,21 @@ private async void Edit_Click(object sender, EventArgs e) CompleteButton.IsVisible = true; SaveResetGrid.IsEnabled = false; - // Create variables for the sketch creation mode and color. - SketchCreationMode creationMode; - // Set the creation mode and UI based on which button called this method. switch (((Button)sender).Text) { case "Point": - creationMode = SketchCreationMode.Point; + _geometryType = GeometryType.Point; Status.Text = "Tap to add a point."; break; case "Polyline": - creationMode = SketchCreationMode.Polyline; + _geometryType = GeometryType.Polyline; Status.Text = "Tap to add a vertex."; break; case "Polygon": - creationMode = SketchCreationMode.Polygon; + _geometryType = GeometryType.Polygon; Status.Text = "Tap to add a vertex."; break; @@ -128,43 +126,13 @@ private async void Edit_Click(object sender, EventArgs e) return; } - // Get the user-drawn geometry. - Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, true); - - // Project the geometry to WGS84 (WGS84 is required by the KML standard). - Geometry projectedGeometry = geometry.Project(SpatialReferences.Wgs84); - - // Create a KmlGeometry using the new geometry. - KmlGeometry kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround); - - // Create a new placemark. - _currentPlacemark = new KmlPlacemark(kmlGeometry); - - // Add the placemark to the KmlDocument. - _kmlDocument.ChildNodes.Add(_currentPlacemark); - - // Choose whether to enable the icon picker or color picker. - IconPicker.IsVisible = creationMode == SketchCreationMode.Point; - ColorPicker.IsVisible = creationMode != SketchCreationMode.Point; - - // Enable the style editing UI. - StyleUI.IsVisible = true; - MainUI.IsVisible = false; + // Start the geometry editor. + MyMapView.GeometryEditor.Start(_geometryType); } catch (ArgumentException) { await Application.Current.MainPage.DisplayAlert("Error", "Unsupported Geometry", "OK"); } - finally - { - // Reset the UI. - ShapeGrid.IsVisible = true; - CompleteButton.IsVisible = false; - Status.Text = "Select the type of feature you would like to add."; - - // Enable the save and reset buttons. - SaveResetGrid.IsEnabled = true; - } } private void Apply_Style_Click(object sender, SelectedItemChangedEventArgs e) @@ -218,11 +186,46 @@ private void Complete_Click(object sender, EventArgs e) { try { - // Finish the sketch. - MyMapView.SketchEditor.CompleteCommand.Execute(null); + // Get the user-drawn geometry. + Geometry geometry = MyMapView.GeometryEditor.Stop(); + + // Check to see if geometry has been drawn. + if (!geometry.IsEmpty) + { + // Project the geometry to WGS84 (WGS84 is required by the KML standard). + Geometry projectedGeometry = geometry.Project(SpatialReferences.Wgs84); + + // Create a KmlGeometry using the new geometry. + KmlGeometry kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround); + + // Create a new placemark. + _currentPlacemark = new KmlPlacemark(kmlGeometry); + + // Add the placemark to the KmlDocument. + _kmlDocument.ChildNodes.Add(_currentPlacemark); + + // Choose whether to enable the icon picker or color picker. + IconPicker.IsVisible = _geometryType == GeometryType.Point; + ColorPicker.IsVisible = _geometryType != GeometryType.Point; + + // Enable the style editing UI. + StyleUI.IsVisible = true; + MainUI.IsVisible = false; + } } - catch (ArgumentException) + catch (Exception ex) { + Debug.WriteLine(ex.Message); + } + finally + { + // Reset the UI. + ShapeGrid.IsVisible = true; + CompleteButton.IsVisible = false; + Status.Text = "Select the type of feature you would like to add."; + + // Enable the save and reset buttons. + SaveResetGrid.IsEnabled = true; } } diff --git a/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.md b/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.md index 56507a7fad..ceebcdd5ac 100644 --- a/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.md +++ b/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.md @@ -17,7 +17,7 @@ Tap on one of the buttons in the middle row to start adding a geometry. Tap on t 1. Create a `KmlDocument` 2. Create a `KmlDataset` using the `KmlDocument`. 3. Create a `KmlLayer` using the `KmlDataset` and add it to `Map.OperationalLayers`. -4. Create `Geometry` using `SketchEditor`. +4. Create `Geometry` using `GeometryEditor`. 5. Project that `Geometry` to WGS84 using `GeometryEngine.Project`. 6. Create a `KmlGeometry` object using that projected `Geometry`. 7. Create a `KmlPlacemark` using the `KmlGeometry`. @@ -28,6 +28,7 @@ Tap on one of the buttons in the middle row to start adding a geometry. Tap on t ## Relevant API * GeometryEngine.Project +* GeometryEditor * KmlDataset * KmlDocument * KmlGeometry @@ -35,8 +36,7 @@ Tap on one of the buttons in the middle row to start adding a geometry. Tap on t * KmlNode.SaveAsASync * KmlPlacemark * KmlStyle -* SketchEditor ## Tags -Keyhole, KML, KMZ, OGC \ No newline at end of file +geometry editor, Keyhole, KML, KMZ, OGC \ No newline at end of file diff --git a/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json b/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json index 833ffa8ecb..cdb7d2f688 100644 --- a/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json +++ b/src/MAUI/Maui.Samples/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json @@ -10,13 +10,15 @@ "KML", "KMZ", "Keyhole", - "OGC" + "OGC", + "geometry editor" ], "offline_data": [], "redirect_from": [ "/net/latest/maui/sample-code/createandsavekmlfile.htm" ], "relevant_apis": [ + "GeometryEditor", "GeometryEngine.Project", "KmlDataset", "KmlDocument", @@ -24,8 +26,7 @@ "KmlLayer", "KmlNode.SaveAsASync", "KmlPlacemark", - "KmlStyle", - "SketchEditor" + "KmlStyle" ], "snippets": [ "CreateAndSaveKmlFile.xaml.cs", diff --git a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs index cdce4665eb..79856eaea4 100644 --- a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs +++ b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs @@ -20,12 +20,15 @@ namespace ArcGIS.Samples.FindServiceArea category: "Network analysis", description: "Find the service area within a network from a given point.", instructions: "In order to find any service areas at least one facility needs to be added to the map view.", - tags: new[] { "barriers", "facilities", "impedance", "logistics", "routing" })] + tags: new[] { "barriers", "facilities", "geometry editor", "impedance", "logistics", "routing" })] public partial class FindServiceArea { // Uri for the service area around San Diego. private Uri _serviceAreaUri = new Uri("https://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/ServiceArea"); + // Hold a reference to the geometry type used in the geometry editor. + private GeometryType _geometryType; + public FindServiceArea() { InitializeComponent(); @@ -45,48 +48,23 @@ private void Initialize() // Create graphics overlays for all of the elements of the map. MyMapView.GraphicsOverlays.Add(new GraphicsOverlay()); - - // Add a new behavior for double taps on the MapView. - MyMapView.GeoViewDoubleTapped += (s, e) => - { - // If the sketch editor complete command is enabled, a sketch is in progress. - if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null)) - { - // Set the event as handled. - e.Handled = true; - - // Finish any drawing. - MyMapView.SketchEditor.CompleteCommand.Execute(null); - - // Reset the UI. - DrawBarrierButton.Text = "Draw barrier"; - } - }; } private async void PlaceFacilityButton_Click(object sender, EventArgs e) { try { - // Let the user tap on the map view using the point sketch mode. - SketchCreationMode creationMode = SketchCreationMode.Point; - Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, false); - - // Symbology for a facility. - PictureMarkerSymbol facilitySymbol = new PictureMarkerSymbol(new Uri("https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png")) + if (MyMapView.GeometryEditor.IsStarted) { - Height = 30, - Width = 30 - }; + MyMapView.GeometryEditor.Stop(); + } - // Create a graphic for the facility. - Graphic facilityGraphic = new Graphic(geometry, new Dictionary() { { "Type", "Facility" } }, facilitySymbol) - { - ZIndex = 2 - }; + // Let the user tap on the map view using the point sketch mode. + _geometryType = GeometryType.Point; - // Add the graphic to the graphics overlay. - MyMapView.GraphicsOverlays[0].Graphics.Add(facilityGraphic); + // Start the geometry editor. + MyMapView.GeometryEditor.Start(_geometryType); + MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; } catch (TaskCanceledException) { @@ -99,14 +77,50 @@ private async void PlaceFacilityButton_Click(object sender, EventArgs e) } } + + private void GeometryEditor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == "Geometry") + { + if (_geometryType == GeometryType.Point) + { + // Disconnect event handler to prevent multiple calls. + MyMapView.GeometryEditor.PropertyChanged -= GeometryEditor_PropertyChanged; + + // Get the active geometry. + Geometry geometry = MyMapView.GeometryEditor.Geometry; + + // Symbology for a facility. + PictureMarkerSymbol facilitySymbol = new PictureMarkerSymbol(new Uri("https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png")) + { + Height = 30, + Width = 30 + }; + + // Create a graphic for the facility. + Graphic facilityGraphic = new Graphic(geometry, new Dictionary() { { "Type", "Facility" } }, facilitySymbol) + { + ZIndex = 2 + }; + + // Add the graphic to the graphics overlay. + MyMapView.GraphicsOverlays[0].Graphics.Add(facilityGraphic); + + // Stop the geometry editor to clear the active geometry. + MyMapView.GeometryEditor.Stop(); + } + } + } + private async void DrawBarrierButton_Click(object sender, EventArgs e) { // Finish drawing barriers if started. - if (DrawBarrierButton.Text != "Draw barrier") + if ((string)DrawBarrierButton.Text != "Draw barrier") { - if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null)) - MyMapView.SketchEditor.CompleteCommand.Execute(null); - + if (MyMapView.GeometryEditor.IsStarted) + { + FinishBarrier(); + } DrawBarrierButton.Text = "Draw barrier"; return; } @@ -116,14 +130,33 @@ private async void DrawBarrierButton_Click(object sender, EventArgs e) DrawBarrierButton.Text = "Finish drawing"; // Let the user draw on the map view using the polyline sketch mode. - SketchCreationMode creationMode = SketchCreationMode.Polyline; - Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, false); + _geometryType = GeometryType.Polyline; + // Start the geometry editor. + MyMapView.GeometryEditor.Start(_geometryType); + } + catch (TaskCanceledException) + { + // Ignore this exception. + } + catch (Exception ex) + { + // Report exceptions. + await Application.Current.MainPage.DisplayAlert("Error", "Error drawing barrier:\n" + ex.Message, "OK"); + } + } + + private void FinishBarrier() + { + Geometry geometry = MyMapView.GeometryEditor.Stop(); + + if (!geometry.IsEmpty) + { // Symbol for the barriers. SimpleLineSymbol barrierSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, System.Drawing.Color.Black, 5.0f); // Create the graphic to be used for barriers. - Graphic barrierGraphic = new Graphic(geometry, new Dictionary() { { "Type", "Barrier" } }, barrierSymbol) + Graphic barrierGraphic = new Graphic(geometry, new Dictionary { { "Type", "Barrier" } }, barrierSymbol) { ZIndex = 1 }; @@ -131,24 +164,14 @@ private async void DrawBarrierButton_Click(object sender, EventArgs e) // Add a graphic from the polyline the user drew. MyMapView.GraphicsOverlays[0].Graphics.Add(barrierGraphic); } - catch (TaskCanceledException) - { - // Ignore this exception. - } - catch (Exception ex) - { - // Report exceptions. - await Application.Current.MainPage.DisplayAlert("Error", "Error drawing barrier:\n" + ex.Message, "OK"); - } } private async void ShowServiceAreasButton_Click(object sender, EventArgs e) { - // Finish any drawing in progress. - if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null)) + // Finish any drawings. + if (MyMapView.GeometryEditor.IsStarted) { - MyMapView.SketchEditor.CompleteCommand.Execute(null); - + MyMapView.GeometryEditor.Stop(); DrawBarrierButton.Text = "Draw barrier"; } diff --git a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.md b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.md index 24b978091a..cf08b939ed 100644 --- a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.md +++ b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.md @@ -40,4 +40,4 @@ In order to find any service areas at least one facility needs to be added to th ## Tags -barriers, facilities, impedance, logistics, routing +barriers, facilities, geometry editor, impedance, logistics, routing diff --git a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json index 3f44c85fab..c8132f857f 100644 --- a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json +++ b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json @@ -9,6 +9,7 @@ "keywords": [ "barriers", "facilities", + "geometry editor", "impedance", "logistics", "routing" diff --git a/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs b/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs index ad0f92e5bc..16c6608632 100644 --- a/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs +++ b/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs @@ -24,7 +24,7 @@ namespace ArcGIS.WPF.Samples.GeodatabaseTransactions category: "Data", description: "Use transactions to manage how changes are committed to a geodatabase.", instructions: "When the sample loads, a feature service is taken offline as a geodatabase. When the geodatabase is ready, you can add multiple types of features. To apply edits directly, uncheck the 'Require a transaction for edits' checkbox. When using transactions, use the buttons to start editing and stop editing. When you stop editing, you can choose to commit the changes or roll them back. At any point, you can synchronize the local geodatabase with the feature service.", - tags: new[] { "commit", "database", "geodatabase", "transact", "transactions" })] + tags: new[] { "commit", "database", "geodatabase", "geometry editor", "transact", "transactions" })] public partial class GeodatabaseTransactions { // URL for the editable feature service. @@ -235,7 +235,7 @@ private void AddNewFeature(object sender, RoutedEventArgs args) // Inform the user which table is being edited. MessageTextBlock.Text = "Click the map to add a new feature to the geodatabase table '" + _editTable.TableName + "'"; - // Use the sketch editor to allow the user to draw a point on the map. + // Use the geometry editor to allow the user to draw a point on the map. MyMapView.GeometryEditor.Start(GeometryType.Point); MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; @@ -266,7 +266,7 @@ private async void GeometryEditor_PropertyChanged(object sender, System.Componen Feature newFeature = _editTable.CreateFeature(); // Create a random value for the 'type' attribute (integer between 1 and 7). - Random random = new Random(DateTime.Now.Millisecond); + Random random = new(DateTime.Now.Millisecond); int featureType = random.Next(1, 7); // Set the geometry with the point the user clicked and the 'type' with the random integer. diff --git a/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json b/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json index 99fd2fd791..c347b56253 100644 --- a/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json +++ b/src/WPF/WPF.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json @@ -10,6 +10,7 @@ "commit", "database", "geodatabase", + "geometry editor", "transact", "transactions" ], @@ -22,7 +23,8 @@ "Geodatabase.BeginTransaction", "Geodatabase.CommitTransaction", "Geodatabase.IsInTransaction", - "Geodatabase.RollbackTransaction" + "Geodatabase.RollbackTransaction", + "GeometryEditor" ], "snippets": [ "GeodatabaseTransactions.xaml.cs", diff --git a/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs b/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs index 68bfd4f9ee..84d6f03fcc 100644 --- a/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs +++ b/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs @@ -10,7 +10,6 @@ using Esri.ArcGISRuntime.Geometry; using Esri.ArcGISRuntime.Mapping; using Esri.ArcGISRuntime.Ogc; -using Esri.ArcGISRuntime.UI; using Microsoft.Win32; using System; using System.Collections.Generic; @@ -28,7 +27,7 @@ namespace ArcGIS.WPF.Samples.CreateAndSaveKmlFile category: "Layers", description: "Construct a KML document and save it as a KMZ file.", instructions: "Click on one of the buttons in the middle row to start adding a geometry. Click on the map view to place vertices. Click the \"Complete Sketch\" button to add the geometry to the KML document as a new KML placemark. Use the style interface to edit the style of the placemark. If you do not wish to set a style, click the \"Don't Apply Style\" button. When you are finished adding KML nodes, click on the \"Save KMZ file\" button to save the active KML document as a .kmz file on your system. Use the \"Reset\" button to clear the current KML document and start a new one.", - tags: new[] { "KML", "KMZ", "Keyhole", "OGC" })] + tags: new[] { "KML", "KMZ", "Keyhole", "OGC", "geometry editor" })] [ArcGIS.Samples.Shared.Attributes.OfflineData()] public partial class CreateAndSaveKmlFile { @@ -36,7 +35,7 @@ public partial class CreateAndSaveKmlFile private KmlDataset _kmlDataset; private KmlLayer _kmlLayer; private KmlPlacemark _currentPlacemark; - private GeometryType _creationMode; + private GeometryType _geometryType; public CreateAndSaveKmlFile() { @@ -97,7 +96,7 @@ private void ResetKml() MyMapView.Map.OperationalLayers.Add(_kmlLayer); } - private async void Edit_Click(object sender, RoutedEventArgs e) + private void Edit_Click(object sender, RoutedEventArgs e) { try { @@ -110,19 +109,19 @@ private async void Edit_Click(object sender, RoutedEventArgs e) switch (((Button)sender).Name) { case nameof(PointButton): - _creationMode = GeometryType.Point; + _geometryType = GeometryType.Point; InstructionsText.Text = "Tap to add a point."; StyleText.Text = "Select an icon for the placemark."; break; case nameof(PolylineButton): - _creationMode = GeometryType.Polyline; + _geometryType = GeometryType.Polyline; InstructionsText.Text = "Tap to add a vertex."; StyleText.Text = "Select a color for the placemark."; break; case nameof(PolygonButton): - _creationMode = GeometryType.Polygon; + _geometryType = GeometryType.Polygon; InstructionsText.Text = "Tap to add a vertex."; StyleText.Text = "Select a color for the placemark."; break; @@ -132,7 +131,7 @@ private async void Edit_Click(object sender, RoutedEventArgs e) } // Start the geometry editor. - MyMapView.GeometryEditor.Start(_creationMode); + MyMapView.GeometryEditor.Start(_geometryType); } catch (ArgumentException) { @@ -205,8 +204,8 @@ private void Complete_Click(object sender, RoutedEventArgs e) MainUI.IsEnabled = false; // Choose whether to enable the icon picker or color picker. - IconPicker.Visibility = _creationMode == GeometryType.Point ? Visibility.Visible : Visibility.Collapsed; - ColorPicker.Visibility = _creationMode != GeometryType.Point ? Visibility.Visible : Visibility.Collapsed; + IconPicker.Visibility = _geometryType == GeometryType.Point ? Visibility.Visible : Visibility.Collapsed; + ColorPicker.Visibility = _geometryType != GeometryType.Point ? Visibility.Visible : Visibility.Collapsed; } } catch (Exception ex) @@ -214,7 +213,7 @@ private void Complete_Click(object sender, RoutedEventArgs e) Debug.WriteLine(ex.Message); } finally - { + { // Reset the UI. ShapesPanel.Visibility = Visibility.Visible; CompleteButton.Visibility = Visibility.Collapsed; diff --git a/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json b/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json index 4f86d8b988..c43e08bc76 100644 --- a/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json +++ b/src/WPF/WPF.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json @@ -10,13 +10,15 @@ "KML", "KMZ", "Keyhole", - "OGC" + "OGC", + "geometry editor" ], "offline_data": [], "redirect_from": [ "/net/latest/wpf/sample-code/createandsavekmlfile.htm" ], "relevant_apis": [ + "GeometryEditor", "GeometryEngine.Project", "KmlDataset", "KmlDocument", @@ -24,8 +26,7 @@ "KmlLayer", "KmlNode.SaveAsASync", "KmlPlacemark", - "KmlStyle", - "SketchEditor" + "KmlStyle" ], "snippets": [ "CreateAndSaveKmlFile.xaml.cs", diff --git a/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs b/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs index 492e24c986..8cd708d8da 100644 --- a/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs +++ b/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs @@ -25,13 +25,15 @@ namespace ArcGIS.WPF.Samples.FindServiceArea category: "Network analysis", description: "Find the service area within a network from a given point.", instructions: "In order to find any service areas at least one facility needs to be added to the map view.", - tags: new[] { "barriers", "facilities", "impedance", "logistics", "routing" })] + tags: new[] { "barriers", "facilities", "geometry editor", "impedance", "logistics", "routing" })] public partial class FindServiceArea { // Uri for the service area around San Diego. private Uri _serviceAreaUri = new Uri("https://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/ServiceArea"); - private GeometryType _creationMode; + // Hold a reference to the geometry type used in the geometry editor. + private GeometryType _geometryType; + public FindServiceArea() { InitializeComponent(); @@ -63,10 +65,10 @@ private void PlaceFacilityButton_Click(object sender, RoutedEventArgs e) } // Let the user tap on the map view using the point sketch mode. - _creationMode = GeometryType.Point; + _geometryType = GeometryType.Point; - MyMapView.GeometryEditor.Start(_creationMode); - MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; ; + MyMapView.GeometryEditor.Start(_geometryType); + MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; } catch (TaskCanceledException) { @@ -83,7 +85,7 @@ private void GeometryEditor_PropertyChanged(object sender, System.ComponentModel { if (e.PropertyName == "Geometry") { - if (_creationMode == GeometryType.Point) + if (_geometryType == GeometryType.Point) { // Disconnect event handler to prevent multiple calls. MyMapView.GeometryEditor.PropertyChanged -= GeometryEditor_PropertyChanged; @@ -131,9 +133,9 @@ private void DrawBarrierButton_Click(object sender, RoutedEventArgs e) DrawBarrierButton.Content = "Finish barrier"; // Let the user draw on the map view using the polyline sketch mode. - _creationMode = GeometryType.Polyline; + _geometryType = GeometryType.Polyline; - MyMapView.GeometryEditor.Start(_creationMode); + MyMapView.GeometryEditor.Start(_geometryType); } catch (TaskCanceledException) { diff --git a/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json b/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json index 6550298578..28e2bbcb44 100644 --- a/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json +++ b/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json @@ -9,6 +9,7 @@ "keywords": [ "barriers", "facilities", + "geometry editor", "impedance", "logistics", "routing" diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs index c57129158c..fe6c0887f3 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs @@ -26,67 +26,70 @@ namespace ArcGIS.WinUI.Samples.GeodatabaseTransactions category: "Data", description: "Use transactions to manage how changes are committed to a geodatabase.", instructions: "When the sample loads, a feature service is taken offline as a geodatabase. When the geodatabase is ready, you can add multiple types of features. To apply edits directly, uncheck the 'Require a transaction for edits' checkbox. When using transactions, use the buttons to start editing and stop editing. When you stop editing, you can choose to commit the changes or roll them back. At any point, you can synchronize the local geodatabase with the feature service.", - tags: new[] { "commit", "database", "geodatabase", "transact", "transactions" })] + tags: new[] { "commit", "database", "geodatabase", "geometry editor", "transact", "transactions" })] public partial class GeodatabaseTransactions { - // URL for the editable feature service + // URL for the editable feature service. private const string SyncServiceUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/SaveTheBaySync/FeatureServer/"; - // Work in a small extent south of Galveston, TX + // Work in a small extent south of Galveston, TX. private Envelope _extent = new Envelope(-95.3035, 29.0100, -95.1053, 29.1298, SpatialReferences.Wgs84); - // Store the local geodatabase to edit + // Store the local geodatabase to edit. private Geodatabase _localGeodatabase; - // Store references to two tables to edit: Birds and Marine points + // Store references to the Birds and Marine points tables. private GeodatabaseFeatureTable _birdTable; private GeodatabaseFeatureTable _marineTable; + // Store a reference to the table to be edited. + private GeodatabaseFeatureTable _editTable; + public GeodatabaseTransactions() { InitializeComponent(); - // When the map view loads, add a new map + // When the map view loads, add a new map. MyMapView.Loaded += (s, e) => { - // Create a new map with the oceans basemap and add it to the map view + // Create a new map with the oceans basemap and add it to the map view. Map map = new Map(BasemapStyle.ArcGISOceans); MyMapView.Map = map; }; - // When the spatial reference changes (the map loads) add the local geodatabase tables as feature layers + // When the spatial reference changes (the map loads) add the local geodatabase tables as feature layers. MyMapView.SpatialReferenceChanged += async (s, e) => { - // Call a function (and await it) to get the local geodatabase (or generate it from the feature service) + // Call a function (and await it) to get the local geodatabase (or generate it from the feature service). await GetLocalGeodatabase(); - // Once the local geodatabase is available, load the tables as layers to the map + // Once the local geodatabase is available, load the tables as layers to the map. await LoadLocalGeodatabaseTables(); }; } private async Task GetLocalGeodatabase() { - // Get the path to the local geodatabase for this platform (temp directory, for example) + // Get the path to the local geodatabase for this platform (temp directory, for example). string localGeodatabasePath = GetGdbPath(); try { - // See if the geodatabase file is already present + // See if the geodatabase file is already present. if (File.Exists(localGeodatabasePath)) { - // If the geodatabase is already available, open it, hide the progress control, and update the message + // If the geodatabase is already available, open it, hide the progress control, and update the message. _localGeodatabase = await Geodatabase.OpenAsync(localGeodatabasePath); LoadingProgressBar.Visibility = Visibility.Collapsed; MessageTextBlock.Text = "Using local geodatabase from '" + _localGeodatabase.Path + "'"; } else { - // Create a new GeodatabaseSyncTask with the uri of the feature server to pull from + // Create a new GeodatabaseSyncTask with the uri of the feature server to pull from. Uri uri = new Uri(SyncServiceUrl); GeodatabaseSyncTask gdbTask = await GeodatabaseSyncTask.CreateAsync(uri); - // Create parameters for the task: layers and extent to include, out spatial reference, and sync model + // Create parameters for the task: layers and extent to include, out spatial reference, and sync model. GenerateGeodatabaseParameters gdbParams = await gdbTask.CreateDefaultGenerateGeodatabaseParametersAsync(_extent); gdbParams.OutSpatialReference = MyMapView.SpatialReference; gdbParams.SyncModel = SyncModel.Layer; @@ -94,18 +97,18 @@ private async Task GetLocalGeodatabase() gdbParams.LayerOptions.Add(new GenerateLayerOption(0)); gdbParams.LayerOptions.Add(new GenerateLayerOption(1)); - // Create a geodatabase job that generates the geodatabase + // Create a geodatabase job that generates the geodatabase. GenerateGeodatabaseJob generateGdbJob = gdbTask.GenerateGeodatabase(gdbParams, localGeodatabasePath); - // Handle the job changed event and check the status of the job; store the geodatabase when it's ready + // Handle the job changed event and check the status of the job; store the geodatabase when it's ready. generateGdbJob.StatusChanged += (s, e) => { - // See if the job succeeded + // See if the job succeeded. if (generateGdbJob.Status == JobStatus.Succeeded) { DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => { - // Hide the progress control and update the message + // Hide the progress control and update the message. LoadingProgressBar.Visibility = Visibility.Collapsed; MessageTextBlock.Text = "Created local geodatabase"; }); @@ -114,20 +117,20 @@ private async Task GetLocalGeodatabase() { DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => { - // Hide the progress control and report the exception + // Hide the progress control and report the exception. LoadingProgressBar.Visibility = Visibility.Collapsed; MessageTextBlock.Text = "Unable to create local geodatabase: " + generateGdbJob.Error.Message; }); } }; - // Start the generate geodatabase job + // Start the generate geodatabase job. _localGeodatabase = await generateGdbJob.GetResultAsync(); } } catch (Exception ex) { - // Show a message for the exception encountered + // Show a message for the exception encountered. DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => { _ = new MessageDialog2("Unable to create offline database: " + ex.Message).ShowAsync(); @@ -135,32 +138,32 @@ private async Task GetLocalGeodatabase() } } - // Function that loads the two point tables from the local geodatabase and displays them as feature layers + // Function that loads the two point tables from the local geodatabase and displays them as feature layers. private async Task LoadLocalGeodatabaseTables() { if (_localGeodatabase == null) { return; } - // Read the geodatabase tables and add them as layers + // Read the geodatabase tables and add them as layers. foreach (GeodatabaseFeatureTable table in _localGeodatabase.GeodatabaseFeatureTables) { try { - // Load the table so the TableName can be read + // Load the table so the TableName can be read. await table.LoadAsync(); - // Store a reference to the Birds table + // Store a reference to the Birds table. if (table.TableName.ToLower().Contains("birds")) { _birdTable = table; } - // Store a reference to the Marine table + // Store a reference to the Marine table. if (table.TableName.ToLower().Contains("marine")) { _marineTable = table; } - // Create a new feature layer to show the table in the map + // Create a new feature layer to show the table in the map. FeatureLayer layer = new FeatureLayer(table); DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => MyMapView.Map.OperationalLayers.Add(layer)); } @@ -170,10 +173,10 @@ private async Task LoadLocalGeodatabaseTables() } } - // Handle the transaction status changed event + // Handle the transaction status changed event. _localGeodatabase.TransactionStatusChanged += GdbTransactionStatusChanged; - // Zoom the map view to the extent of the generated local datasets + // Zoom the map view to the extent of the generated local datasets. DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => { MyMapView.SetViewpoint(new Viewpoint(_marineTable.Extent)); @@ -183,15 +186,15 @@ private async Task LoadLocalGeodatabaseTables() private void GdbTransactionStatusChanged(object sender, TransactionStatusChangedEventArgs e) { - // Update UI controls based on whether the geodatabase has a current transaction + // Update UI controls based on whether the geodatabase has a current transaction. DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => { - // These buttons should be enabled when there IS a transaction + // These buttons should be enabled when there IS a transaction. AddBirdButton.IsEnabled = e.IsInTransaction; AddMarineButton.IsEnabled = e.IsInTransaction; StopEditingButton.IsEnabled = e.IsInTransaction; - // These buttons should be enabled when there is NOT a transaction + // These buttons should be enabled when there is NOT a transaction. StartEditingButton.IsEnabled = !e.IsInTransaction; SyncEditsButton.IsEnabled = !e.IsInTransaction; }); @@ -199,80 +202,97 @@ private void GdbTransactionStatusChanged(object sender, TransactionStatusChanged private string GetGdbPath() { - // Get the UWP-specific path for storing the geodatabase + // Get the UWP-specific path for storing the geodatabase. string folder = Windows.Storage.ApplicationData.Current.LocalFolder.Path; return Path.Combine(folder, "savethebay.geodatabase"); } private void BeginTransaction(object sender, RoutedEventArgs e) { - // See if there is a transaction active for the geodatabase + // See if there is a transaction active for the geodatabase. if (!_localGeodatabase.IsInTransaction) { - // If not, begin a transaction + // If not, begin a transaction. _localGeodatabase.BeginTransaction(); MessageTextBlock.Text = "Transaction started"; } } - private async void AddNewFeature(object sender, RoutedEventArgs args) + private void AddNewFeature(object sender, RoutedEventArgs args) { - // See if it was the "Birds" or "Marine" button that was clicked + // See if it was the "Birds" or "Marine" button that was clicked. Button addFeatureButton = (Button)sender; try { - // Cancel execution of the sketch task if it is already active - if (MyMapView.SketchEditor.CancelCommand.CanExecute(null)) + // Cancel execution of the sketch task if it is already active. + if (MyMapView.GeometryEditor.IsStarted) { - MyMapView.SketchEditor.CancelCommand.Execute(null); + MyMapView.GeometryEditor.Stop(); } - // Store the correct table to edit (for the button clicked) - GeodatabaseFeatureTable editTable = null; + // Store the correct table to edit (for the button clicked). if (addFeatureButton == AddBirdButton) { - editTable = _birdTable; + _editTable = _birdTable; } else { - editTable = _marineTable; + _editTable = _marineTable; } - // Inform the user which table is being edited - MessageTextBlock.Text = "Click the map to add a new feature to the geodatabase table '" + editTable.TableName + "'"; - - // Create a random value for the 'type' attribute (integer between 1 and 7) - Random random = new Random(DateTime.Now.Millisecond); - int featureType = random.Next(1, 7); - - // Use the sketch editor to allow the user to draw a point on the map - MapPoint clickPoint = await MyMapView.SketchEditor.StartAsync(Esri.ArcGISRuntime.UI.SketchCreationMode.Point, false) as MapPoint; - - // Create a new feature (row) in the selected table - Feature newFeature = editTable.CreateFeature(); + // Inform the user which table is being edited. + MessageTextBlock.Text = "Click the map to add a new feature to the geodatabase table '" + _editTable.TableName + "'"; - // Set the geometry with the point the user clicked and the 'type' with the random integer - newFeature.Geometry = clickPoint; - newFeature.SetAttributeValue("type", featureType); - - // Add the new feature to the table - await editTable.AddFeatureAsync(newFeature); + // Use the geometry editor to allow the user to draw a point on the map. + MyMapView.GeometryEditor.Start(GeometryType.Point); - // Clear the message - MessageTextBlock.Text = "New feature added to the '" + editTable.TableName + "' table"; + MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; } catch (TaskCanceledException) { - // Ignore if the edit was canceled + // Ignore if the edit was canceled. } catch (Exception ex) { - // Report other exception messages + // Report other exception messages. MessageTextBlock.Text = ex.Message; } } + private async void GeometryEditor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + // Check if the user finished drawing a point on the map. + if (e.PropertyName == "Geometry") + { + // Disconnect event handler to prevent multiple calls. + MyMapView.GeometryEditor.PropertyChanged -= GeometryEditor_PropertyChanged; + + // Get the active geometry. + Geometry geometry = MyMapView.GeometryEditor.Geometry; + + // Create a new feature (row) in the selected table. + Feature newFeature = _editTable.CreateFeature(); + + // Create a random value for the 'type' attribute (integer between 1 and 7). + Random random = new Random(DateTime.Now.Millisecond); + int featureType = random.Next(1, 7); + + // Set the geometry with the point the user clicked and the 'type' with the random integer. + newFeature.Geometry = geometry; + newFeature.SetAttributeValue("type", featureType); + + // Add the new feature to the table. + await _editTable.AddFeatureAsync(newFeature); + + // Set the newly created feature message. + MessageTextBlock.Text = "New feature added to the '" + _editTable.TableName + "' table"; + + // Stop the geometry editor, clearing the active geometry. + MyMapView.GeometryEditor.Stop(); + } + } + private async void StopEditTransaction(object sender, RoutedEventArgs e) { // Create a new dialog that prompts for commit, rollback, or cancel @@ -287,32 +307,32 @@ private async void StopEditTransaction(object sender, RoutedEventArgs e) try { - // Ask the user if they want to commit or rollback the transaction (or cancel to keep working in the transaction) + // 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.Label == commitCommand.Label) { - // See if there is a transaction active for the geodatabase + // 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) + // 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.Label == rollbackCommand.Label) { - // See if there is a transaction active for the geodatabase + // 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) + // 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 + // For 'cancel' don't end the transaction with a commit or rollback. } } catch @@ -320,16 +340,16 @@ private async void StopEditTransaction(object sender, RoutedEventArgs e) } } - // Change which controls are enabled if the user chooses to require/not require transactions for edits + // Change which controls are enabled if the user chooses to require/not require transactions for edits. private void RequireTransactionChanged(object sender, RoutedEventArgs e) { - // If the local geodatabase isn't created yet, return + // If the local geodatabase isn't created yet, return. if (_localGeodatabase == null) { return; } - // Get the value of the "require transactions" checkbox + // Get the value of the "require transactions" checkbox. bool mustHaveTransaction = RequireTransactionCheckBox.IsChecked == true; - // Warn the user if disabling transactions while a transaction is active + // Warn the user if disabling transactions while a transaction is active. if (!mustHaveTransaction && _localGeodatabase.IsInTransaction) { _ = new MessageDialog2("Stop editing to end the current transaction.", "Current Transaction").ShowAsync(); @@ -337,34 +357,34 @@ private void RequireTransactionChanged(object sender, RoutedEventArgs e) return; } - // Enable or disable controls according to the checkbox value + // Enable or disable controls according to the checkbox value. StartEditingButton.IsEnabled = mustHaveTransaction; StopEditingButton.IsEnabled = mustHaveTransaction && _localGeodatabase.IsInTransaction; AddBirdButton.IsEnabled = !mustHaveTransaction; AddMarineButton.IsEnabled = !mustHaveTransaction; } - // Synchronize edits in the local geodatabase with the service + // Synchronize edits in the local geodatabase with the service. public async void SynchronizeEdits(object sender, RoutedEventArgs e) { - // Show the progress bar while the sync is working + // Show the progress bar while the sync is working. LoadingProgressBar.Visibility = Visibility.Visible; try { - // Create a sync task with the URL of the feature service to sync + // Create a sync task with the URL of the feature service to sync. GeodatabaseSyncTask syncTask = await GeodatabaseSyncTask.CreateAsync(new Uri(SyncServiceUrl)); - // Create sync parameters + // Create sync parameters. SyncGeodatabaseParameters taskParameters = await syncTask.CreateDefaultSyncGeodatabaseParametersAsync(_localGeodatabase); - // Create a synchronize geodatabase job, pass in the parameters and the geodatabase + // Create a synchronize geodatabase job, pass in the parameters and the geodatabase. SyncGeodatabaseJob job = syncTask.SyncGeodatabase(taskParameters, _localGeodatabase); - // Handle the JobChanged event for the job + // Handle the JobChanged event for the job. job.StatusChanged += (s, arg) => { - // Report changes in the job status + // Report changes in the job status. if (job.Status == JobStatus.Succeeded) { // Report success ... @@ -382,17 +402,17 @@ public async void SynchronizeEdits(object sender, RoutedEventArgs e) } }; - // Await the completion of the job + // Await the completion of the job. await job.GetResultAsync(); } catch (Exception ex) { - // Show the message if an exception occurred + // Show the message if an exception occurred. MessageTextBlock.Text = "Error when synchronizing: " + ex.Message; } finally { - // Hide the progress bar when the sync job is complete + // Hide the progress bar when the sync job is complete. LoadingProgressBar.Visibility = Visibility.Collapsed; } } diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.md index 2b53af0a46..9912665d03 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.md +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.md @@ -27,6 +27,7 @@ When the sample loads, a feature service is taken offline as a geodatabase. When * Geodatabase.CommitTransaction * Geodatabase.IsInTransaction * Geodatabase.RollbackTransaction +* GeometryEditor ## About the data @@ -34,4 +35,4 @@ The sample uses a publicly-editable, sync-enabled [feature service](https://samp ## Tags -commit, database, geodatabase, transact, transactions \ No newline at end of file +commit, database, geodatabase, geometry editor, transact, transactions \ No newline at end of file diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json index bae3b4017c..e77a825a96 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Data/GeodatabaseTransactions/readme.metadata.json @@ -10,6 +10,7 @@ "commit", "database", "geodatabase", + "geometry editor", "transact", "transactions" ], @@ -22,7 +23,8 @@ "Geodatabase.BeginTransaction", "Geodatabase.CommitTransaction", "Geodatabase.IsInTransaction", - "Geodatabase.RollbackTransaction" + "Geodatabase.RollbackTransaction", + "GeometryEditor" ], "snippets": [ "GeodatabaseTransactions.xaml.cs", diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs index 5d2cbe98e5..8df1855324 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs @@ -11,11 +11,11 @@ using Esri.ArcGISRuntime.Geometry; using Esri.ArcGISRuntime.Mapping; using Esri.ArcGISRuntime.Ogc; -using Esri.ArcGISRuntime.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; @@ -29,7 +29,7 @@ namespace ArcGIS.WinUI.Samples.CreateAndSaveKmlFile category: "Layers", description: "Construct a KML document and save it as a KMZ file.", instructions: "Click on one of the buttons in the middle row to start adding a geometry. Click on the map view to place vertices. Click the \"Complete Sketch\" button to add the geometry to the KML document as a new KML placemark. Use the style interface to edit the style of the placemark. If you do not wish to set a style, click the \"Don't Apply Style\" button. When you are finished adding KML nodes, click on the \"Save KMZ file\" button to save the active KML document as a .kmz file on your system. Use the \"Reset\" button to clear the current KML document and start a new one.", - tags: new[] { "KML", "KMZ", "Keyhole", "OGC" })] + tags: new[] { "KML", "KMZ", "Keyhole", "OGC", "geometry editor" })] [ArcGIS.Samples.Shared.Attributes.OfflineData()] public partial class CreateAndSaveKmlFile { @@ -37,6 +37,7 @@ public partial class CreateAndSaveKmlFile private KmlDataset _kmlDataset; private KmlLayer _kmlLayer; private KmlPlacemark _currentPlacemark; + private GeometryType _geometryType; public CreateAndSaveKmlFile() { @@ -97,26 +98,23 @@ private async void Edit_Click(object sender, RoutedEventArgs e) CompleteButton.Visibility = Visibility.Visible; SaveResetGrid.Visibility = Visibility.Collapsed; - // Create variables for the sketch creation mode and color. - SketchCreationMode creationMode; - // Set the creation mode and UI based on which button called this method. switch (((Button)sender).Name) { case nameof(PointButton): - creationMode = SketchCreationMode.Point; + _geometryType = GeometryType.Point; InstructionsText.Text = "Tap to add a point."; StyleText.Text = "Select an icon for the placemark."; break; case nameof(PolylineButton): - creationMode = SketchCreationMode.Polyline; + _geometryType = GeometryType.Polyline; InstructionsText.Text = "Tap to add a vertex."; StyleText.Text = "Select a color for the placemark."; break; case nameof(PolygonButton): - creationMode = SketchCreationMode.Polygon; + _geometryType = GeometryType.Polygon; InstructionsText.Text = "Tap to add a vertex."; StyleText.Text = "Select a color for the placemark."; break; @@ -125,43 +123,14 @@ private async void Edit_Click(object sender, RoutedEventArgs e) return; } - // Get the user-drawn geometry. - Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, true); - - // Project the geometry to WGS84 (WGS84 is required by the KML standard). - Geometry projectedGeometry = geometry.Project(SpatialReferences.Wgs84); - - // Create a KmlGeometry using the new geometry. - KmlGeometry kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround); - - // Create a new placemark. - _currentPlacemark = new KmlPlacemark(kmlGeometry); + // Start the geometry editor. + MyMapView.GeometryEditor.Start(_geometryType); - // Add the placemark to the KmlDocument. - _kmlDocument.ChildNodes.Add(_currentPlacemark); - - // Enable the style editing UI. - StyleBorder.Visibility = Visibility.Visible; - MainUI.Visibility = Visibility.Collapsed; - - // Display the Icon picker or the color picker based on the creation mode. - IconPicker.Visibility = creationMode == SketchCreationMode.Point ? Visibility.Visible : Visibility.Collapsed; - ColorSelector.Visibility = creationMode != SketchCreationMode.Point ? Visibility.Visible : Visibility.Collapsed; } catch (ArgumentException) { await new MessageDialog2("Unsupported Geometry", "Error").ShowAsync(); } - finally - { - // Reset the UI. - ShapesPanel.Visibility = Visibility.Visible; - CompleteButton.Visibility = Visibility.Collapsed; - InstructionsText.Text = "Select the type of feature you would like to add."; - - // Enable the save and reset buttons. - SaveResetGrid.Visibility = Visibility; - } } private void Apply_Style_Click(object sender, RoutedEventArgs e) @@ -210,11 +179,46 @@ private void Complete_Click(object sender, RoutedEventArgs e) { try { - // Finish the sketch. - MyMapView.SketchEditor.CompleteCommand.Execute(null); + // Get the user-drawn geometry. + Geometry geometry = MyMapView.GeometryEditor.Stop(); + + // Check to see if geometry has been drawn. + if (!geometry.IsEmpty) + { + // Project the geometry to WGS84 (WGS84 is required by the KML standard). + Geometry projectedGeometry = geometry.Project(SpatialReferences.Wgs84); + + // Create a KmlGeometry using the new geometry. + KmlGeometry kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround); + + // Create a new placemark. + _currentPlacemark = new KmlPlacemark(kmlGeometry); + + // Add the placemark to the KmlDocument. + _kmlDocument.ChildNodes.Add(_currentPlacemark); + + // Enable the style editing UI. + StyleBorder.Visibility = Visibility.Visible; + MainUI.Visibility = Visibility.Collapsed; + + // Display the Icon picker or the color picker based on the creation mode. + IconPicker.Visibility = _geometryType == GeometryType.Point ? Visibility.Visible : Visibility.Collapsed; + ColorSelector.Visibility = _geometryType != GeometryType.Point ? Visibility.Visible : Visibility.Collapsed; + } } - catch (ArgumentException) + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + } + finally { + // Reset the UI. + ShapesPanel.Visibility = Visibility.Visible; + CompleteButton.Visibility = Visibility.Collapsed; + InstructionsText.Text = "Select the type of feature you would like to add."; + + // Enable the save and reset buttons. + SaveResetGrid.Visibility = Visibility; } } diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.md index 11da843fc8..d5e450b662 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.md +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.md @@ -17,7 +17,7 @@ Click on one of the buttons in the middle row to start adding a geometry. Click 1. Create a `KmlDocument` 2. Create a `KmlDataset` using the `KmlDocument`. 3. Create a `KmlLayer` using the `KmlDataset` and add it to `Map.OperationalLayers`. -4. Create `Geometry` using `SketchEditor`. +4. Create `Geometry` using `GeometryEditor`. 5. Project that `Geometry` to WGS84 using `GeometryEngine.Project`. 6. Create a `KmlGeometry` object using that projected `Geometry`. 7. Create a `KmlPlacemark` using the `KmlGeometry`. @@ -28,6 +28,7 @@ Click on one of the buttons in the middle row to start adding a geometry. Click ## Relevant API * GeometryEngine.Project +* GeometryEditor * KmlDataset * KmlDocument * KmlGeometry @@ -35,8 +36,7 @@ Click on one of the buttons in the middle row to start adding a geometry. Click * KmlNode.SaveAsASync * KmlPlacemark * KmlStyle -* SketchEditor ## Tags -Keyhole, KML, KMZ, OGC \ No newline at end of file +geometry editor, Keyhole, KML, KMZ, OGC \ No newline at end of file diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json index 9e63933e8e..1667df2c43 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Layers/CreateAndSaveKmlFile/readme.metadata.json @@ -10,13 +10,15 @@ "KML", "KMZ", "Keyhole", - "OGC" + "OGC", + "geometry editor" ], "offline_data": [], "redirect_from": [ "/net/latest/winui/sample-code/createandsavekmlfile.htm" ], "relevant_apis": [ + "GeometryEditor", "GeometryEngine.Project", "KmlDataset", "KmlDocument", @@ -24,8 +26,7 @@ "KmlLayer", "KmlNode.SaveAsASync", "KmlPlacemark", - "KmlStyle", - "SketchEditor" + "KmlStyle" ], "snippets": [ "CreateAndSaveKmlFile.xaml.cs", diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs index 83eb2ef073..feb7aa1435 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs @@ -25,12 +25,15 @@ namespace ArcGIS.WinUI.Samples.FindServiceArea category: "Network analysis", description: "Find the service area within a network from a given point.", instructions: "In order to find any service areas at least one facility needs to be added to the map view.", - tags: new[] { "barriers", "facilities", "impedance", "logistics", "routing" })] + tags: new[] { "barriers", "facilities", "geometry editor", "impedance", "logistics", "routing" })] public partial class FindServiceArea { // Uri for the service area around San Diego. private Uri _serviceAreaUri = new Uri("https://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/ServiceArea"); + // Hold a reference to the geometry type used in the geometry editor. + private GeometryType _geometryType; + public FindServiceArea() { InitializeComponent(); @@ -50,46 +53,23 @@ private void Initialize() // Create graphics overlays for all of the elements of the map. MyMapView.GraphicsOverlays.Add(new GraphicsOverlay()); - - // Add a new behavior for double taps on the MapView. - MyMapView.GeoViewDoubleTapped += (s, e) => - { - // If the sketch editor complete command is enabled, a sketch is in progress. - if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null)) - { - // Set the event as handled. - e.Handled = true; - - // Finish the sketch. - MyMapView.SketchEditor.CompleteCommand.Execute(null); - DrawBarrierButton.Content = "Draw barrier"; - } - }; } private async void PlaceFacilityButton_Click(object sender, RoutedEventArgs e) { try { - // Let the user tap on the map view using the point sketch mode. - SketchCreationMode creationMode = SketchCreationMode.Point; - Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, false); - - // Symbology for a facility. - PictureMarkerSymbol facilitySymbol = new PictureMarkerSymbol(new Uri("https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png")) + if (MyMapView.GeometryEditor.IsStarted) { - Height = 30, - Width = 30 - }; + MyMapView.GeometryEditor.Stop(); + } - // Create a graphic for the facility. - Graphic facilityGraphic = new Graphic(geometry, new Dictionary() { { "Type", "Facility" } }, facilitySymbol) - { - ZIndex = 2 - }; + // Let the user tap on the map view using the point sketch mode. + _geometryType = GeometryType.Point; - // Add the graphic to the graphics overlay. - MyMapView.GraphicsOverlays[0].Graphics.Add(facilityGraphic); + // Start the geometry editor. + MyMapView.GeometryEditor.Start(_geometryType); + MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged; } catch (TaskCanceledException) { @@ -102,13 +82,49 @@ private async void PlaceFacilityButton_Click(object sender, RoutedEventArgs e) } } + private void GeometryEditor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == "Geometry") + { + if (_geometryType == GeometryType.Point) + { + // Disconnect event handler to prevent multiple calls. + MyMapView.GeometryEditor.PropertyChanged -= GeometryEditor_PropertyChanged; + + // Get the active geometry. + Geometry geometry = MyMapView.GeometryEditor.Geometry; + + // Symbology for a facility. + PictureMarkerSymbol facilitySymbol = new PictureMarkerSymbol(new Uri("https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png")) + { + Height = 30, + Width = 30 + }; + + // Create a graphic for the facility. + Graphic facilityGraphic = new Graphic(geometry, new Dictionary() { { "Type", "Facility" } }, facilitySymbol) + { + ZIndex = 2 + }; + + // Add the graphic to the graphics overlay. + MyMapView.GraphicsOverlays[0].Graphics.Add(facilityGraphic); + + // Stop the geometry editor to clear the active geometry. + MyMapView.GeometryEditor.Stop(); + } + } + } + private async void DrawBarrierButton_Click(object sender, RoutedEventArgs e) { // Finish the drawing if already started. if ((string)DrawBarrierButton.Content != "Draw barrier") { - if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null)) - MyMapView.SketchEditor.CompleteCommand.Execute(null); + if (MyMapView.GeometryEditor.IsStarted) + { + FinishBarrier(); + } DrawBarrierButton.Content = "Draw barrier"; return; } @@ -118,9 +134,28 @@ private async void DrawBarrierButton_Click(object sender, RoutedEventArgs e) DrawBarrierButton.Content = "Finish drawing"; // Let the user draw on the map view using the polyline sketch mode. - SketchCreationMode creationMode = SketchCreationMode.Polyline; - Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, false); + _geometryType = GeometryType.Polyline; + // Start the geometry editor. + MyMapView.GeometryEditor.Start(_geometryType); + } + catch (TaskCanceledException) + { + // Ignore this exception. + } + catch (Exception ex) + { + // Report exceptions. + await new MessageDialog2("Error drawing barrier:\n" + ex.Message, "Sample error").ShowAsync(); + } + } + + private void FinishBarrier() + { + Geometry geometry = MyMapView.GeometryEditor.Stop(); + + if (!geometry.IsEmpty) + { // Symbol for the barriers. SimpleLineSymbol barrierSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, System.Drawing.Color.Black, 5.0f); @@ -133,25 +168,14 @@ private async void DrawBarrierButton_Click(object sender, RoutedEventArgs e) // Add a graphic from the polyline the user drew. MyMapView.GraphicsOverlays[0].Graphics.Add(barrierGraphic); } - catch (TaskCanceledException) - { - // Ignore this exception. - } - catch (Exception ex) - { - // Report exceptions. - await new MessageDialog2("Error drawing barrier:\n" + ex.Message, "Sample error").ShowAsync(); - } } private async void ShowServiceAreasButton_Click(object sender, RoutedEventArgs e) { - // Finish any sketches in progress. - // If the sketch editor complete command is enabled, a sketch is in progress. - if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null)) + // Finish any drawings. + if (MyMapView.GeometryEditor.IsStarted) { - // Finish the sketch. - MyMapView.SketchEditor.CompleteCommand.Execute(null); + MyMapView.GeometryEditor.Stop(); DrawBarrierButton.Content = "Draw barrier"; } diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.md index 3d6ef3fa86..a3854a8902 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.md +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.md @@ -40,4 +40,4 @@ In order to find any service areas at least one facility needs to be added to th ## Tags -barriers, facilities, impedance, logistics, routing +barriers, facilities, geometry editor, impedance, logistics, routing diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json index c8798823ef..ec69ff5705 100644 --- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json +++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/NetworkAnalysis/FindServiceArea/readme.metadata.json @@ -9,6 +9,7 @@ "keywords": [ "barriers", "facilities", + "geometry editor", "impedance", "logistics", "routing"