diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 4be69cae68..388bae509b 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -1,7 +1,7 @@
true
- 200.4.0
+ 200.5.0
@@ -15,24 +15,24 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
\ No newline at end of file
diff --git a/src/MAUI/Maui.Samples/ArcGIS.Samples.Maui.csproj b/src/MAUI/Maui.Samples/ArcGIS.Samples.Maui.csproj
index ba0f3c1125..52cf16d57e 100644
--- a/src/MAUI/Maui.Samples/ArcGIS.Samples.Maui.csproj
+++ b/src/MAUI/Maui.Samples/ArcGIS.Samples.Maui.csproj
@@ -100,7 +100,6 @@
-
@@ -108,16 +107,11 @@
-
-
-
-
- PreserveNewest
diff --git a/src/MAUI/Maui.Samples/Helpers/ArcGISLoginPrompt.cs b/src/MAUI/Maui.Samples/Helpers/ArcGISLoginPrompt.cs
index 3e34be3b1e..068fd9ece3 100644
--- a/src/MAUI/Maui.Samples/Helpers/ArcGISLoginPrompt.cs
+++ b/src/MAUI/Maui.Samples/Helpers/ArcGISLoginPrompt.cs
@@ -70,28 +70,8 @@ public static async Task EnsureAGOLCredentialAsync()
public static void SetChallengeHandler()
{
- // Define the server information for ArcGIS Online
- ServerInfo portalServerInfo = new ServerInfo(new Uri(ArcGISOnlineUrl))
- {
- TokenAuthenticationType = TokenAuthenticationType.OAuthAuthorizationCode,
- OAuthClientInfo = new OAuthClientInfo(AppClientId, new Uri(OAuthRedirectUrl))
- };
-
- // If a client secret has been configured, set the authentication type to OAuth client credentials.
- if (!string.IsNullOrEmpty(ClientSecret))
- {
- // If a client secret is specified then use the TokenAuthenticationType.OAuthClientCredentials type.
- portalServerInfo.TokenAuthenticationType = TokenAuthenticationType.OAuthClientCredentials;
- portalServerInfo.OAuthClientInfo.ClientSecret = ClientSecret;
- }
-
- // Register this server with AuthenticationManager.
- AuthenticationManager.Current.RegisterServer(portalServerInfo);
-
- // Use a function in this class to challenge for credentials.
- AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(PromptCredentialAsync);
-
- // Set the OAuthAuthorizeHandler component (this class) for Android or iOS platforms.
+ var userConfig = new OAuthUserConfiguration(new Uri(ArcGISOnlineUrl), AppClientId, new Uri(OAuthRedirectUrl));
+ AuthenticationManager.Current.OAuthUserConfigurations.Add(userConfig);
AuthenticationManager.Current.OAuthAuthorizeHandler = new OAuthAuthorize();
}
diff --git a/src/MAUI/Maui.Samples/Platforms/Windows/App.xaml.cs b/src/MAUI/Maui.Samples/Platforms/Windows/App.xaml.cs
index e4bdf066b4..9e05342126 100644
--- a/src/MAUI/Maui.Samples/Platforms/Windows/App.xaml.cs
+++ b/src/MAUI/Maui.Samples/Platforms/Windows/App.xaml.cs
@@ -14,6 +14,8 @@ public partial class App : MauiWinUIApplication
///
public App()
{
+ if (WinUIEx.WebAuthenticator.CheckOAuthRedirectionActivation())
+ return;
this.InitializeComponent();
}
diff --git a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_Android.jpg b/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_Android.jpg
deleted file mode 100644
index e4a14069c1..0000000000
Binary files a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_Android.jpg and /dev/null differ
diff --git a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_MacCatalyst.jpg b/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_MacCatalyst.jpg
deleted file mode 100644
index c37ee2d85f..0000000000
Binary files a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_MacCatalyst.jpg and /dev/null differ
diff --git a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_Windows.jpg b/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_Windows.jpg
deleted file mode 100644
index c37ee2d85f..0000000000
Binary files a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_Windows.jpg and /dev/null differ
diff --git a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_iOS.jpg b/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_iOS.jpg
deleted file mode 100644
index 45d15c26f2..0000000000
Binary files a/src/MAUI/Maui.Samples/Resources/Thumbnails/Placeholder_iOS.jpg and /dev/null differ
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
index 33986e68bf..d5c9b5339c 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
@@ -16,97 +16,120 @@
-
+
\ No newline at end of file
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
index fba890ab65..11592b7b63 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
@@ -21,7 +21,7 @@ namespace ArcGIS.Samples.CreateAndEditGeometries
name: "Create and edit geometries",
category: "Geometry",
description: "Use the Geometry Editor to create new point, multipoint, polyline, or polygon geometries or to edit existing geometries by interacting with a map view.",
- instructions: "To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).",
+ instructions: "To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map and then perform edits by tapping and dragging its elements. When using an appropriate tool to select a whole geometry, you can use the control handles to scale and rotate the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or one of the available `ShapeTool`s).",
tags: new[] { "draw", "edit", "freehand", "geometry editor", "sketch", "vertex" })]
public partial class CreateAndEditGeometries
{
@@ -102,6 +102,7 @@ private void Initialize()
_toolDictionary = new Dictionary()
{
{ "Vertex Tool", new VertexTool() },
+ { "Reticle Vertex Tool", new ReticleVertexTool() },
{ "Freehand Tool", new FreehandTool() },
{ "Arrow Shape Tool", ShapeTool.Create(ShapeToolType.Arrow) },
{ "Ellipse Shape Tool", ShapeTool.Create(ShapeToolType.Ellipse) },
@@ -166,7 +167,7 @@ private void PolylineButton_Click(object sender, EventArgs e)
if (!_geometryEditor.IsStarted)
{
// Disable buttons to reflect that the geometry editor has started.
- DisableOtherGeometryButtons(PointButton);
+ DisableOtherGeometryButtons(PolylineButton);
_geometryEditor.Start(GeometryType.Polyline);
}
@@ -178,7 +179,7 @@ private void PolygonButton_Click(object sender, EventArgs e)
if (!_geometryEditor.IsStarted)
{
// Disable buttons to reflect that the geometry editor has started.
- DisableOtherGeometryButtons(PointButton);
+ DisableOtherGeometryButtons(PolygonButton);
_geometryEditor.Start(GeometryType.Polygon);
}
@@ -192,7 +193,10 @@ private void ToolPicker_SelectedIndexChanged(object sender, EventArgs e)
// Account for case when vertex tool is selected and geometry editor is started with a polyline or polygon geometry type.
// Ensure point and multipoint buttons are only enabled when the selected tool is a vertex tool.
- PointButton.IsEnabled = MultipointButton.IsEnabled = !_geometryEditor.IsStarted && tool is VertexTool;
+ PointButton.IsEnabled = MultipointButton.IsEnabled = !_geometryEditor.IsStarted && (tool is VertexTool || tool is ReticleVertexTool);
+
+ // Uniform scale is not compatible with the reticle vertex tool.
+ UniformScaleCheckBox.IsEnabled = !(_geometryEditor.Tool is ReticleVertexTool);
}
// Set the scale mode for every geometry editor tool.
@@ -318,6 +322,20 @@ private async void MyMapView_GeoViewTapped(object sender, Esri.ArcGISRuntime.Mau
_selectedGraphic.IsVisible = false;
}
+ private void ToggleGeometryEditorPanelButton_Pressed(object sender, EventArgs e)
+ {
+ GeometryEditorPanel.IsVisible = !GeometryEditorPanel.IsVisible;
+
+ if (GeometryEditorPanel.IsVisible)
+ {
+ ToggleGeometryEditorPanelButton.Text = "Hide UI";
+ }
+ else
+ {
+ ToggleGeometryEditorPanelButton.Text = "Show UI";
+ }
+ }
+
#endregion Event handlers
#region Helper methods
@@ -358,7 +376,7 @@ private void ResetFromEditingSession()
_selectedGraphic = null;
// Point and multipoint sessions do not support the vertex tool.
- PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool;
+ PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool || _geometryEditor.Tool is ReticleVertexTool;
PolylineButton.IsEnabled = PolygonButton.IsEnabled = true;
ToolPicker.IsEnabled = true;
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/createandeditgeometries.jpg b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/createandeditgeometries.jpg
index d00cfe48a3..23d3ac81d7 100644
Binary files a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/createandeditgeometries.jpg and b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/createandeditgeometries.jpg differ
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/readme.md b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/readme.md
index 866e1cf714..e26742e7a3 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/readme.md
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/CreateAndEditGeometries/readme.md
@@ -10,7 +10,9 @@ A field worker can mark features of interest on a map using an appropriate geome
## How to use the sample
-To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).
+To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map and then perform edits by tapping and dragging its elements. When using an appropriate tool to select a whole geometry, you can use the control handles to scale and rotate the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or one of the available `ShapeTool`s).
+
+When using the `ReticleVertexTool`, you can move the map position of the reticle by dragging and zooming the map. Insert a vertex under the reticle by tapping on the map. Move a vertex by tapping when the reticle is located over a vertex, drag the map to move the position of the reticle, then tap a second time to place the vertex.
Use the control panel to undo or redo changes made to the geometry, delete a selected element, save the geometry, stop the editing session and discard any edits, and remove all geometries from the map.
@@ -23,7 +25,7 @@ Use the control panel to undo or redo changes made to the geometry, delete a sel
* Access the `MapView.IdentifyGraphicsOverlayAsync(...)`.
* Find the desired graphic in the `results.FirstOrDefault()` list.
* Access the geometry associated with the `Graphic` using `Graphic.Geometry` - this will be used in the `GeometryEditor.Start(Geometry)` method.
-3. Create `VertexTool`, `FreehandTool`, or `ShapeTool` objects which define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
+3. Create `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or `ShapeTool` objects to define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
4. Edit a tool's InteractionConfiguration to set the GeometryEditorScaleMode to allow either uniform or stretch scale mode.
5. Check to see if undo and redo are possible during an editing session using `GeometryEditor.CanUndo` and `GeometryEditor.CanRedo`. If it's possible, use `GeometryEditor.Undo()` and `GeometryEditor.Redo()`.
6. Check whether the currently selected `GeometryEditorElement` can be deleted (`GeometryEditor.SelectedElement.CanDelete`). If the element can be deleted, delete using `GeometryEditor.DeleteSelectedElement()`.
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
index d3e9f23981..395fe14426 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
@@ -5,7 +5,7 @@
xmlns:esriUI="clr-namespace:Esri.ArcGISRuntime.Maui;assembly=Esri.ArcGISRuntime.Maui">
-
+
@@ -13,7 +13,7 @@
+ WidthRequest="160" />
+ VerticalOptions="Start">
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
@@ -122,11 +146,12 @@
FontAttributes="Bold"
FontSize="14"
Text="Select snap sources" />
-
+
+ WidthRequest="250" />
-
+ WidthRequest="250" />
+
+
+
+
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
index 92e92a2284..3cbe39224f 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
@@ -11,6 +11,7 @@
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Maui;
+using Esri.ArcGISRuntime.Toolkit.Maui;
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.UI.Editing;
using Microsoft.Maui.ApplicationModel;
@@ -25,7 +26,7 @@ namespace ArcGIS.Samples.SnapGeometryEdits
category: "Geometry",
description: "Use the Geometry Editor to edit a geometry and align it to existing geometries on a map.",
instructions: "To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.",
- tags: new[] { "edit", "feature", "geometry editor", "layers", "map", "snapping" })]
+ tags: new[] { "edit", "feature", "geometry editor", "graphics", "layers", "map", "snapping" })]
public partial class SnapGeometryEdits : ContentPage
{
// Hold references for use in event handlers.
@@ -86,14 +87,14 @@ private async Task Initialize()
MultipointButton
};
- // Enable magnifier on mobile platforms.
-#if ANDROID || IOS
- MyMapView.InteractionOptions = new Esri.ArcGISRuntime.UI.MapViewInteractionOptions
+ // Hide the popup when user taps screen.
+ SnappingSettingsPopup.GestureRecognizers.Add(new TapGestureRecognizer
{
- IsMagnifierEnabled = true,
- AllowMagnifierToPan = true
- };
-#endif
+ Command = new Command(() =>
+ {
+ SnappingSettingsPopup.IsVisible = false;
+ })
+ });
// Add an event handler to detect geoview tapped events.
MyMapView.GeoViewTapped += MyMapView_GeoViewTapped;
@@ -114,6 +115,9 @@ private void SetSnapSettings()
// Populate lists of snap source settings for point and polyline layers.
PointSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Point).ToList();
PolylineSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Polyline).ToList();
+
+ // Populate a list of snap source settings for graphics overlays.
+ GraphicsOverlaySnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingsVMs => snapSourceSettingsVMs.SnapSourceSettings.Source is GraphicsOverlay).ToList();
}
private void CreateNewGraphic()
@@ -279,6 +283,18 @@ private void DiscardButton_Click(object sender, EventArgs e)
#endregion
#region Geometry Tool Buttons Handlers
+ private void ReticleVertexToolSwitch_Toggled(object sender, ToggledEventArgs e)
+ {
+ if (ReticleVertexToolSwitch.IsToggled)
+ {
+ _geometryEditor.Tool = new ReticleVertexTool();
+ }
+ else
+ {
+ _geometryEditor.Tool = new VertexTool();
+ }
+ }
+
private void PointButton_Click(object sender, EventArgs e)
{
if (_geometryEditor.IsStarted)
@@ -336,11 +352,6 @@ private void ShowSnapSettingsButton_Clicked(object sender, EventArgs e)
{
SnappingSettingsPopup.IsVisible = true;
}
-
- private void HideSnapSettingsButton_Clicked(object sender, EventArgs e)
- {
- SnappingSettingsPopup.IsVisible = false;
- }
#endregion
}
@@ -353,10 +364,18 @@ public SnapSourceSettingsVM(SnapSourceSettings snapSourceSettings)
{
SnapSourceSettings = snapSourceSettings;
- if (snapSourceSettings.Source is FeatureLayer featureLayer && featureLayer.FeatureTable != null)
+ if (snapSourceSettings.Source is FeatureLayer featureLayer)
{
Name = featureLayer.Name;
- GeometryType = featureLayer.FeatureTable.GeometryType;
+
+ if (featureLayer.FeatureTable != null)
+ {
+ GeometryType = featureLayer.FeatureTable.GeometryType;
+ }
+ }
+ else if (snapSourceSettings.Source is GraphicsOverlay graphicsOverlay)
+ {
+ Name = "Editor graphics overlay";
}
IsEnabled = snapSourceSettings.IsEnabled;
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.md b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.md
index 450c1216ea..5cb74ddf5d 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.md
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.md
@@ -12,11 +12,11 @@ A field worker can create new features by editing and snapping the vertices of a
To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.
-To configure snapping, press the snap settings button to enable or disable snapping and choose which layers to snap to.
+To configure snapping, press the snap settings button to enable or disable snapping and choose which snap sources to snap to.
-To interactively snap a vertex, ensure that snapping is enabled and move the mouse pointer or drag a vertex to nearby an existing feature. When the pointer is close to a feature, the edit position will be adjusted to coincide with (or snap to), edges and vertices of that feature. Tap or release the touch pointer to place the vertex at the snapped location.
+To interactively snap a vertex to a feature or graphic, ensure that snapping is enabled for the relevant snap source and move the mouse pointer or drag a vertex to nearby an existing feature or graphic. When the pointer is close to that existing geoelement, the edit position will be adjusted to coincide with (or snap to), edges and vertices of its geometry. Tap or release the touch pointer to place the vertex at the snapped location.
-To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features.
+To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features or graphics.
To undo changes made to the geometry, press the undo button.
@@ -39,6 +39,7 @@ To save your edits, press the save button.
* Geometry
* GeometryEditor
* GeometryEditorStyle
+* GraphicsOverlay
* MapView
* SnapSettings
* SnapSource
@@ -54,8 +55,8 @@ Snapping is used to maintain data integrity between different sources of data wh
To snap to polygon and polyline layers, the recommended approach is to set the `FeatureLayer`'s feature tiling mode to `FeatureTilingMode.EnabledWithFullResolutionWhenSupported` and use the default `ServiceFeatureTable` feature request mode `FeatureRequestMode.OnInteractionCache`. Local data sources, such as geodatabases, always provide full resolution geometries. Point and multipoint feature layers are also always full resolution.
-Snapping can be used during interactive edits that move existing vertices using the `VertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the magnifier to perform a vertex move allows users of touch devices to clearly see the visual cues for snapping.
+Snapping can be used during interactive edits that move existing vertices using the `VertexTool` or `ReticleVertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the `ReticleVertexTool` to add and move vertices allows users of touch screen devices to clearly see the visual cues for snapping.
## Tags
-edit, feature, geometry editor, layers, map, snapping
+edit, feature, geometry editor, graphics, layers, map, snapping
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.metadata.json b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
index 54b0cf71e8..9a42a65e65 100644
--- a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
+++ b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
@@ -10,6 +10,7 @@
"edit",
"feature",
"geometry editor",
+ "graphics",
"layers",
"map",
"snapping"
@@ -23,6 +24,7 @@
"Geometry",
"GeometryEditor",
"GeometryEditorStyle",
+ "GraphicsOverlay",
"MapView",
"SnapSettings",
"SnapSource",
diff --git a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/snapgeometryedits.jpg b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/snapgeometryedits.jpg
index 0de61a3a89..cab4ba2ca2 100644
Binary files a/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/snapgeometryedits.jpg and b/src/MAUI/Maui.Samples/Samples/Geometry/SnapGeometryEdits/snapgeometryedits.jpg differ
diff --git a/src/MAUI/Maui.Samples/Samples/Layers/BrowseOAFeatureService/BrowseOAFeatureService.xaml b/src/MAUI/Maui.Samples/Samples/Layers/BrowseOAFeatureService/BrowseOAFeatureService.xaml
index 299730a36e..79f7553553 100644
--- a/src/MAUI/Maui.Samples/Samples/Layers/BrowseOAFeatureService/BrowseOAFeatureService.xaml
+++ b/src/MAUI/Maui.Samples/Samples/Layers/BrowseOAFeatureService/BrowseOAFeatureService.xaml
@@ -1,6 +1,7 @@
@@ -27,7 +28,9 @@
SelectionMode="Single">
-
+
+
+
diff --git a/src/MAUI/Maui.Samples/Samples/Layers/BrowseWfsLayers/BrowseWfsLayers.xaml b/src/MAUI/Maui.Samples/Samples/Layers/BrowseWfsLayers/BrowseWfsLayers.xaml
index aa61d3f9e4..96ef67e8cb 100644
--- a/src/MAUI/Maui.Samples/Samples/Layers/BrowseWfsLayers/BrowseWfsLayers.xaml
+++ b/src/MAUI/Maui.Samples/Samples/Layers/BrowseWfsLayers/BrowseWfsLayers.xaml
@@ -2,6 +2,7 @@
@@ -18,7 +19,9 @@
SelectionMode="Single">
-
+
+
+
diff --git a/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml
new file mode 100644
index 0000000000..3947c0ba74
--- /dev/null
+++ b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs
new file mode 100644
index 0000000000..aa301c1523
--- /dev/null
+++ b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs
@@ -0,0 +1,109 @@
+// Copyright 2024 Esri.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
+// language governing permissions and limitations under the License.
+
+using Esri.ArcGISRuntime.Mapping;
+
+namespace ArcGIS.Samples.CreateDynamicBasemapGallery
+{
+ [ArcGIS.Samples.Shared.Attributes.Sample(
+ name: "Create dynamic basemap gallery",
+ category: "Map",
+ description: "Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.",
+ instructions: "When launched, this sample displays a map containing a button that, when pressed, displays a gallery of all styles available in the basemap styles service. Selecting a style results in the drop-down menus at the base of the gallery becoming enabled or disabled. A disabled menu indicates that the customization cannot be applied to the selected style. Once a style and any desired customizations have been selected, pressing `Load` will update the basemap in the map view.",
+ tags: new[] { "basemap", "languages", "service", "style" })]
+ [ArcGIS.Samples.Shared.Attributes.OfflineData()]
+ public partial class CreateDynamicBasemapGallery
+ {
+ public CreateDynamicBasemapGallery()
+ {
+ InitializeComponent();
+ _ = Initialize();
+ }
+
+ private async Task Initialize()
+ {
+ // Create a new map with the ArcGIS Navigation basemap style.
+ MyMapView.Map = new Map(BasemapStyle.ArcGISNavigation);
+
+ // Create a new basemap styles service, pulling in the available styles and their information.
+ BasemapStylesServiceInfo service = await BasemapStylesServiceInfo.CreateAsync();
+
+ // Populate the basemap style gallery.
+ BasemapStyleGallery.ItemsSource = service.StylesInfo;
+
+ // Listen for basemap style selection events.
+ BasemapStyleGallery.SelectionChanged += BasemapStyleGallery_SelectionChanged;
+ }
+
+ private void BasemapStyleGallery_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ // Get the selected basemap style info.
+ var styleInfo = (BasemapStyleInfo)BasemapStyleGallery.SelectedItem;
+
+ // Set the pickers to the available options for the selected basemap.
+ StrategyPicker.ItemsSource = styleInfo.LanguageStrategies.ToList();
+ LanguagePicker.ItemsSource = styleInfo.Languages.ToList();
+ WorldviewPicker.ItemsSource = styleInfo.Worldviews.ToList();
+
+ // Disable any pickers that have no items.
+ LanguagePicker.IsEnabled = styleInfo.Languages.Any();
+ WorldviewPicker.IsEnabled = styleInfo.Worldviews.Any();
+ StrategyPicker.IsEnabled = styleInfo.LanguageStrategies.Any();
+ }
+
+ private void LoadButton_Click(object sender, EventArgs e)
+ {
+ // Return if no basemap style is selected.
+ if (BasemapStyleGallery.SelectedItem == null) return;
+
+ // Create a new basemap style parameters object.
+ var basemapStyleParameters = new BasemapStyleParameters();
+
+ // Set the language to the selected language.
+ if (LanguagePicker.SelectedItem != null)
+ basemapStyleParameters.SpecificLanguage = (LanguagePicker.SelectedItem as BasemapStyleLanguageInfo).CultureInfo;
+
+ // Set the worldview to the selected worldview.
+ if (WorldviewPicker.SelectedItem != null)
+ basemapStyleParameters.Worldview = (WorldviewPicker.SelectedItem as Worldview);
+
+ // Set the strategy to the selected strategy.
+ if (StrategyPicker.SelectedItem != null)
+ basemapStyleParameters.LanguageStrategy = (BasemapStyleLanguageStrategy)StrategyPicker.SelectedItem;
+
+ // Determine the basemap style of the currently selected basemap.
+ BasemapStyle selectedBasemapStyle = ((BasemapStyleInfo)BasemapStyleGallery.SelectedItem).Style;
+
+ // Update the map's basemap.
+ MyMapView.Map.Basemap = new Basemap(selectedBasemapStyle, basemapStyleParameters);
+
+ // Hide the gallery.
+ HideGallery();
+ }
+
+ private void ShowGallery_Clicked(object sender, EventArgs e)
+ {
+ DynamicBasemapStyleGallery.IsVisible = true;
+ TransparentBackground.IsVisible = true;
+ ShowGalleryButton.IsEnabled = false;
+ }
+
+ private void TapGestureRecognizer_Tapped(object sender, TappedEventArgs e)
+ {
+ HideGallery();
+ }
+
+ private void HideGallery()
+ {
+ DynamicBasemapStyleGallery.IsVisible = false;
+ TransparentBackground.IsVisible = false;
+ ShowGalleryButton.IsEnabled = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/createdynamicbasemapgallery.jpg b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/createdynamicbasemapgallery.jpg
new file mode 100644
index 0000000000..8edc0be93a
Binary files /dev/null and b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/createdynamicbasemapgallery.jpg differ
diff --git a/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/readme.md b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/readme.md
new file mode 100644
index 0000000000..f11e8565b5
--- /dev/null
+++ b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/readme.md
@@ -0,0 +1,41 @@
+# Create dynamic basemap gallery
+
+Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.
+
+![CreateDynamicBasemapGallery](createdynamicbasemapgallery.jpg)
+
+## Use case
+
+Multi-use and/or international applications benefit from the ability to change a basemap's style or localize the basemap. For example, an application used for ecological surveys might include navigation functionality to guide an ecologist to a location and functionality for inputting data. When traveling, a user is likely to benefit from a map with a style that emphasizes the transport infrastructure (e.g. `ArcGIS Navigation`). However, during surveys a user is likely to benefit from a map with a style that highlights features in the terrain (e.g. `ArcGIS Terrain`). Implementing a basemap gallery with customization options in an application gives a user the freedom to select a basemap with a style and features (e.g. language of labels) suitable for the task they are undertaking. Making the basemap gallery dynamic ensures the latest customization options are automatically included.
+
+## How to use the sample
+
+When launched, this sample displays a map containing a button that, when pressed, displays a gallery of all styles available in the basemap styles service. Selecting a style results in the drop-down menus at the base of the gallery becoming enabled or disabled. A disabled menu indicates that the customization cannot be applied to the selected style. Once a style and any desired customizations have been selected, pressing `Load` will update the basemap in the map view.
+
+## How it works
+
+* Instantiate and load a `BasemapStylesServiceInfo` object.
+* Access the list of `BasemapStyleInfo` objects using `BasemapStylesServiceInfo.StylesInfo`. These `BasemapStyleInfo` objects contain up-to-date information about each of the styles supported by the Maps SDK, including:
+ * `StyleName`: The human-readable name of the style.
+ * `Style`: The `BasemapStyle` enumeration value representing this style in the Maps SDK.
+ * `Thumbnail`: An image that can be used to display a preview of the style.
+ * `Languages`: A list of `BasemapStyleLanguageInfo` objects, which provide information about each of the specific languages that can be used to customize labels on the style.
+ * `Worldviews`: A list of `Worldview` objects, which provide information about each representation of a disputed boundary that can be used to customize boundaries on the style.
+* The information contained in the list of `BasemapStyleInfo` objects can be used as the data model for a basemap gallery UI component.
+
+## Relevant API
+
+* BasemapStyleInfo
+* BasemapStyleLanguageInfo
+* BasemapStyleParameters
+* BasemapStylesService
+* BasemapStylesServiceInfo
+* Worldview
+
+## Additional information
+
+This sample demonstrates how to implement a basemap gallery using the Maps SDK. The styles and associated customization options used for the gallery are retrieved from the [basemap styles service](https://developers.arcgis.com/rest/basemap-styles/). A ready-made basemap gallery component is also available in the toolkit's provided with each SDK. To see how the ready-made basemap gallery toolkit component can be integrated into a Maps SDK application refer to the `Set Basemap` sample.
+
+## Tags
+
+basemap, languages, service, style
diff --git a/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json
new file mode 100644
index 0000000000..daec418ea3
--- /dev/null
+++ b/src/MAUI/Maui.Samples/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json
@@ -0,0 +1,32 @@
+{
+ "category": "Map",
+ "description": "Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.",
+ "formal_name": "CreateDynamicBasemapGallery",
+ "ignore": false,
+ "images": [
+ "createdynamicbasemapgallery.jpg"
+ ],
+ "keywords": [
+ "basemap",
+ "languages",
+ "service",
+ "style"
+ ],
+ "offline_data": [],
+ "redirect_from": [
+ "/net/latest/maui/sample-code/create-dynamic-basemap-gallery.htm"
+ ],
+ "relevant_apis": [
+ "BasemapStyleInfo",
+ "BasemapStyleLanguageInfo",
+ "BasemapStyleParameters",
+ "BasemapStylesService",
+ "BasemapStylesServiceInfo",
+ "Worldview"
+ ],
+ "snippets": [
+ "CreateDynamicBasemapGallery.xaml.cs",
+ "CreateDynamicBasemapGallery.xaml"
+ ],
+ "title": "Create dynamic basemap gallery"
+}
\ No newline at end of file
diff --git a/src/MAUI/Maui.Samples/Samples/Map/MapReferenceScale/MapReferenceScale.xaml b/src/MAUI/Maui.Samples/Samples/Map/MapReferenceScale/MapReferenceScale.xaml
index fd8de1fa65..32ccccb7ba 100644
--- a/src/MAUI/Maui.Samples/Samples/Map/MapReferenceScale/MapReferenceScale.xaml
+++ b/src/MAUI/Maui.Samples/Samples/Map/MapReferenceScale/MapReferenceScale.xaml
@@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:esriUI="clr-namespace:Esri.ArcGISRuntime.Maui;assembly=Esri.ArcGISRuntime.Maui"
+ xmlns:mapping="clr-namespace:Esri.ArcGISRuntime.Mapping;assembly=Esri.ArcGISRuntime"
xmlns:resources="clr-namespace:ArcGIS.Resources">
@@ -26,7 +27,9 @@
SelectionMode="None"
VerticalOptions="Center">
-
+
+
+
+
+
+
+
+
+
diff --git a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/OfflineRouting.xaml.cs b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/OfflineRouting.xaml.cs
index 4990855b20..153c6db5a6 100644
--- a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/OfflineRouting.xaml.cs
+++ b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/OfflineRouting.xaml.cs
@@ -94,8 +94,8 @@ private async Task Initialize()
_availableTravelModes = _offlineRouteTask.RouteTaskInfo.TravelModes.ToList();
// Update the UI with the travel modes list.
- TravelModesCombo.ItemsSource = _availableTravelModes.ToList();
- TravelModesCombo.SelectedIndex = 0;
+ TravelModesCollection.ItemsSource = _availableTravelModes.ToList();
+ TravelModesCollection.SelectedItem = _availableTravelModes.First();
// Create the default parameters.
_offlineRouteParameters = await _offlineRouteTask.CreateDefaultParametersAsync();
@@ -105,7 +105,7 @@ private async Task Initialize()
// Now that the sample is ready, hook up the tap event.
MyMapView.GeoViewTapped += MapView_Tapped;
- TravelModesCombo.SelectedIndexChanged += TravelMode_SelectionChanged;
+ TravelModesCollection.SelectionChanged += TravelModesCollection_SelectionChanged;
}
catch (Exception e)
{
@@ -254,21 +254,26 @@ private void MapView_Tapped(object sender, Esri.ArcGISRuntime.Maui.GeoViewInputE
_ = AddStop(e.Position);
// Update the route with the final list of stops.
- _ = UpdateRoute((TravelMode)TravelModesCombo.SelectedItem);
+ _ = UpdateRoute((TravelMode)TravelModesCollection.SelectedItem);
}
- private void TravelMode_SelectionChanged(object sender, EventArgs e)
+ private void ShowMessage(string title, string detail)
+ {
+ Application.Current.MainPage.DisplayAlert(title, detail, "OK");
+ }
+
+ private void TravelModesCollection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
// Enforce selection to prevent errors.
- if (TravelModesCombo.SelectedItem == null)
+ if (TravelModesCollection.SelectedItem == null)
{
- TravelModesCombo.SelectedItem = _availableTravelModes.First();
+ TravelModesCollection.SelectedItem = _availableTravelModes.First();
}
// Update the route.
- _ = UpdateRoute((TravelMode)TravelModesCombo.SelectedItem);
+ _ = UpdateRoute((TravelMode)TravelModesCollection.SelectedItem);
}
catch (Exception ex)
{
@@ -276,10 +281,5 @@ private void TravelMode_SelectionChanged(object sender, EventArgs e)
ShowMessage("Couldn't change travel mode", "Couldn't change travel mode. See debug output for details.");
}
}
-
- private void ShowMessage(string title, string detail)
- {
- Application.Current.MainPage.DisplayAlert(title, detail, "OK");
- }
}
}
\ No newline at end of file
diff --git a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/offlinerouting.jpg b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/offlinerouting.jpg
index d06fabb759..12682103ef 100644
Binary files a/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/offlinerouting.jpg and b/src/MAUI/Maui.Samples/Samples/NetworkAnalysis/OfflineRouting/offlinerouting.jpg differ
diff --git a/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.md b/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.md
index 025553161b..79529b3bb6 100644
--- a/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.md
+++ b/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.md
@@ -14,17 +14,17 @@ When you run the sample, the app will load a web map which contains premium cont
## How it works
-1. Set the `AuthenticationManager`'s `ChallengeHandler`.
-2. Create a `ServerInfo` specifying the portal URL, client ID, and redirect URL.
-3. Register the server with the authentication manager.
+1. Create a `OAuthUserConfiguration` specifying the portal URL, app id, and redirect URL.
+2. Set the `AuthenticationManager`'s `OAuthUserConfigurations` with the new `OAuthUserConfiguration`.
+3. Set the `AuthenticationManager`'s `OAuthAuthorizeHandler` to an instance of a class which implements `IOAuthAuthorizationHandler`.
4. Load a map with premium content requiring authentication to automatically invoke the authentication handler.
## Relevant API
* AuthenticationManager
-* OAuthConfiguration
+* OAuthTokenCredential
+* OAuthUserConfiguration
* PortalItem
-* ServerInfo
## Additional information
@@ -35,4 +35,4 @@ For additional information on using Oauth in your app, see the [Mobile and Nativ
## Tags
-authentication, cloud, credential, OAuth, OAuth2, portal, security
\ No newline at end of file
+authentication, cloud, credential, OAuth, OAuth2, portal, security
diff --git a/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.metadata.json b/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.metadata.json
index 010b5d33de..1887c4003d 100644
--- a/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.metadata.json
+++ b/src/MAUI/Maui.Samples/Samples/Security/OAuth/readme.metadata.json
@@ -21,9 +21,9 @@
],
"relevant_apis": [
"AuthenticationManager",
- "OAuthConfiguration",
- "PortalItem",
- "ServerInfo"
+ "OAuthTokenCredential",
+ "OAuthUserConfiguration",
+ "PortalItem"
],
"snippets": [
"OAuth.xaml.cs",
diff --git a/src/MAUI/Maui.Samples/ViewModels/SearchViewModel.cs b/src/MAUI/Maui.Samples/ViewModels/SearchViewModel.cs
index 730038a8b4..828c838466 100644
--- a/src/MAUI/Maui.Samples/ViewModels/SearchViewModel.cs
+++ b/src/MAUI/Maui.Samples/ViewModels/SearchViewModel.cs
@@ -12,9 +12,29 @@ public partial class SearchViewModel : ObservableObject
private IDispatcherTimer _delaySearchTimer;
private const int _delayedTextChangedTimeout = 500;
+ private Dictionary
+ _sampleKeywords = new();
+
+ private static readonly HashSet _commonWords = ["in", "a", "of", "the", "by", "an", "and"];
+
+ private List _results;
+
+ [GeneratedRegex("[^a-zA-Z0-9 -]")]
+ private static partial Regex NonWordCharRegex();
+
public SearchViewModel()
{
SearchItems = new ObservableCollection();
+
+ // Initialize the dictionary of sample keywords.
+ foreach (var sample in SampleManager.Current.AllSamples.ToList())
+ {
+ string[] sampleNameKeywords = GetKeywords(sample.SampleName).Append(sample.FormalName.ToLower()).ToArray();
+ var categoryKeywords = GetKeywords(sample.Category);
+ var descriptionKeywords = GetKeywords(sample.Description);
+ var tagsKeywords = sample.Tags.ToArray();
+ _sampleKeywords.Add(sample, (sampleNameKeywords, categoryKeywords, descriptionKeywords, tagsKeywords));
+ }
}
[ObservableProperty]
@@ -62,23 +82,18 @@ void PerformSearch()
List sampleResults = new List();
- foreach (var sample in SampleManager.Current.AllSamples.ToList())
+ foreach (var sample in _sampleKeywords)
{
int score = 0;
- var sampleNameKeywords = GetKeywords(sample.SampleName);
- var categoryKeywords = GetKeywords(sample.Category);
- var descriptionKeywords = GetKeywords(sample.Description);
- var tagsKeywords = sample.Tags.ToArray();
-
- score += GetMatches(sampleNameKeywords, searchKeywords) * 6;
- score += GetMatches(categoryKeywords, searchKeywords) * 3;
- score += GetMatches(descriptionKeywords, searchKeywords) * 2;
- score += GetMatches(tagsKeywords, searchKeywords);
+ score += GetMatches(sample.Value.nameKeywords, searchKeywords) * 6;
+ score += GetMatches(sample.Value.categoryKeywords, searchKeywords) * 3;
+ score += GetMatches(sample.Value.descriptionKeywords, searchKeywords) * 2;
+ score += GetMatches(sample.Value.tagsKeywords, searchKeywords);
if (score > 0)
{
- sampleResults.Add(new SearchResultViewModel(sample, score));
+ sampleResults.Add(new SearchResultViewModel(sample.Key, score));
}
}
@@ -87,6 +102,12 @@ void PerformSearch()
if (sampleResults.Count != 0)
{
sampleResults = sampleResults.OrderByDescending(sampleResults => sampleResults.Score).ThenBy(sampleResults => sampleResults.SampleName).ToList();
+ _results = sampleResults;
+
+ // Limit the number of search results to 15
+ if (sampleResults.Count > 15)
+ sampleResults = sampleResults[0..15];
+
SearchItems = new ObservableCollection(sampleResults);
}
else
@@ -101,6 +122,18 @@ void PerformSearch()
}
}
+ [RelayCommand]
+ void BatchResults()
+ {
+ var startIndex = SearchItems.Count;
+ var endIndex = Math.Min(startIndex + 15, _results.Count);
+
+ if (endIndex >= _results.Count) return;
+
+ foreach(var result in _results[startIndex..endIndex])
+ SearchItems.Add(result);
+ }
+
private static int GetMatches(string[] contentKeywords, string[] searchKeywords)
{
int matches = 0;
@@ -126,18 +159,13 @@ private static int GetMatches(string[] contentKeywords, string[] searchKeywords)
private static string[] GetKeywords(string text)
{
// Remove punctuation from the search text and any trailing white space at the end.
- Regex regex = new Regex("[^a-zA-Z0-9 -]");
- text = regex.Replace(text, "");
-
- var cleanedTextWords = text.TrimEnd().ToLower().Split(" ").Distinct().ToList();
- var commonWords = new string[] { "in", "a", "of", "the", "by", "an", "and" };
-
- foreach (var word in commonWords)
- {
- cleanedTextWords.Remove(word);
- }
+ text = NonWordCharRegex().Replace(text, "").ToLower();
- return cleanedTextWords.ToArray();
+ // Split the text into words, remove duplicates, and filter out common words in one go.
+ return text.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
+ .Distinct()
+ .Where(static word => !_commonWords.Contains(word))
+ .ToArray();
}
private void SearchTextChanged()
diff --git a/src/MAUI/Maui.Samples/Views/SearchPage.xaml b/src/MAUI/Maui.Samples/Views/SearchPage.xaml
index 5db56c3cfa..8dd7a8ee1d 100644
--- a/src/MAUI/Maui.Samples/Views/SearchPage.xaml
+++ b/src/MAUI/Maui.Samples/Views/SearchPage.xaml
@@ -19,7 +19,11 @@
-
+
diff --git a/src/MAUI/readme.md b/src/MAUI/readme.md
index a3258403bb..5db79742a6 100644
--- a/src/MAUI/readme.md
+++ b/src/MAUI/readme.md
@@ -163,6 +163,7 @@
* [Change basemap](Maui.Samples/Samples/Map/ChangeBasemap) - Change a map's basemap. A basemap is beneath all layers on a `Map` and is used to provide visual reference for the operational layers.
* [Configure basemap style parameters](Maui.Samples/Samples/Map/ConfigureBasemapStyleParameters) - Apply basemap style parameters customization for a basemap, such as displaying all labels in a specific language or displaying every label in their corresponding local language.
* [Create and save map](Maui.Samples/Samples/Map/AuthorMap) - Create and save a map as an ArcGIS `PortalItem` (i.e. web map).
+* [Create dynamic basemap gallery](Maui.Samples/Samples/Map/CreateDynamicBasemapGallery) - Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.
* [Display map](Maui.Samples/Samples/Map/DisplayMap) - Display a map with an imagery basemap.
* [Display overview map](Maui.Samples/Samples/Map/DisplayOverviewMap) - Include an overview or inset map as an additional map view to show the wider context of the primary view.
* [Download preplanned map area](Maui.Samples/Samples/Map/DownloadPreplannedMap) - Take a map offline using a preplanned map area.
diff --git a/src/Samples.Shared/Managers/LicenseStrings.cs b/src/Samples.Shared/Managers/LicenseStrings.cs
index 9f4d415aa9..5f08499dc4 100644
--- a/src/Samples.Shared/Managers/LicenseStrings.cs
+++ b/src/Samples.Shared/Managers/LicenseStrings.cs
@@ -14,6 +14,8 @@ internal static partial class LicenseStrings
public static string ArcGISAnalysisLicenseKey { get; } = null; // Spatial Analyst Extension License Key
- public static string[] ExtensionLicenses => new[] { ArcGISUtilityNetworkLicenseKey, ArcGISAnalysisLicenseKey }.Where(l => !string.IsNullOrEmpty(l)).ToArray();
+ public static string ArcGISAdvancedEditingUserTypeLicenseKey { get; } = null; // Advanced Editing User Type Extension License Key
+
+ public static string[] ExtensionLicenses => new[] { ArcGISUtilityNetworkLicenseKey, ArcGISAnalysisLicenseKey, ArcGISAdvancedEditingUserTypeLicenseKey}.Where(l => !string.IsNullOrEmpty(l)).ToArray();
}
}
diff --git a/src/Samples.Shared/Resources/FeaturedSamples.xml b/src/Samples.Shared/Resources/FeaturedSamples.xml
index df38409bbd..d0a4c6186e 100644
--- a/src/Samples.Shared/Resources/FeaturedSamples.xml
+++ b/src/Samples.Shared/Resources/FeaturedSamples.xml
@@ -26,6 +26,7 @@
ConfigureBasemapStyleParametersDisplayMapDisplayOverviewMap
+ CreateDynamicBasemapGalleryFilterFeaturesInScene
diff --git a/src/UWP/ArcGIS.UWP.Viewer/ArcGIS.UWP.Viewer.csproj b/src/UWP/ArcGIS.UWP.Viewer/ArcGIS.UWP.Viewer.csproj
index 102f5861bb..9e8dc6f4e4 100644
--- a/src/UWP/ArcGIS.UWP.Viewer/ArcGIS.UWP.Viewer.csproj
+++ b/src/UWP/ArcGIS.UWP.Viewer/ArcGIS.UWP.Viewer.csproj
@@ -121,6 +121,8 @@
+
+
@@ -179,6 +181,7 @@
+
@@ -190,7 +193,6 @@
-
@@ -386,6 +388,9 @@
+
+ SnapGeometryEdits.xaml
+ LocationDrivenGeotriggers.xaml
@@ -705,6 +710,9 @@
CutGeometry.xaml
+
+ CreateAndEditGeometries.xaml
+ CreateGeometries.xaml
@@ -747,9 +755,6 @@
IdentifyGraphics.xaml
-
- SketchOnMap.xaml
- SurfacePlacements.xaml
@@ -999,6 +1004,10 @@
+
+ Designer
+ MSBuild:Compile
+ MSBuild:CompileDesigner
@@ -1407,6 +1416,10 @@
MSBuild:CompileDesigner
+
+ MSBuild:Compile
+ Designer
+ MSBuild:CompileDesigner
@@ -1463,10 +1476,6 @@
MSBuild:CompileDesigner
-
- MSBuild:Compile
- Designer
- MSBuild:CompileDesigner
@@ -1801,6 +1810,9 @@
App.xaml
+
+ PreserveNewest
+ PreserveNewest
@@ -1883,7 +1895,6 @@
PreserveNewest
-
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Converters/InverseBoolConverter.cs b/src/UWP/ArcGIS.UWP.Viewer/Converters/InverseBoolConverter.cs
new file mode 100644
index 0000000000..2e51ece2ff
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Converters/InverseBoolConverter.cs
@@ -0,0 +1,32 @@
+// Copyright 2016 Esri.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
+// language governing permissions and limitations under the License.
+
+using System;
+using Windows.UI.Xaml.Data;
+
+namespace ArcGIS.UWP.Viewer.Converters
+{
+ public class InverseBoolConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string culture)
+ {
+ if (value is bool)
+ {
+ return !(bool)value;
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs b/src/UWP/ArcGIS.UWP.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs
index 11831c7f94..1fb826a77f 100644
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Data/GeodatabaseTransactions/GeodatabaseTransactions.xaml.cs
@@ -7,11 +7,13 @@
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
// Language governing permissions and limitations under the License.
+using Esri.ArcGISRuntime;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Tasks;
using Esri.ArcGISRuntime.Tasks.Offline;
+using Esri.ArcGISRuntime.UI.Editing;
using System;
using System.IO;
using System.Threading.Tasks;
@@ -43,6 +45,9 @@ public partial class GeodatabaseTransactions
private GeodatabaseFeatureTable _birdTable;
private GeodatabaseFeatureTable _marineTable;
+ // Store a reference to the table to be edited.
+ private GeodatabaseFeatureTable _editTable;
+
public GeodatabaseTransactions()
{
InitializeComponent();
@@ -216,64 +221,78 @@ private void BeginTransaction(object sender, RoutedEventArgs e)
}
}
- 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))
- {
- MyMapView.SketchEditor.CancelCommand.Execute(null);
- }
-
- // 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);
+ if (!MyMapView.GeometryEditor.IsStarted)
+ {
+ // 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";
- }
- catch (TaskCanceledException)
- {
- // Ignore if the edit was canceled
+ MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged;
+ }
}
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 == nameof(GeometryEditor.Geometry) && MyMapView.GeometryEditor.Geometry?.IsEmpty == false)
+ {
+ // Disconnect event handler to prevent multiple calls.
+ MyMapView.GeometryEditor.PropertyChanged -= GeometryEditor_PropertyChanged;
+
+ // Get the active geometry.
+ Geometry geometry = MyMapView.GeometryEditor.Stop();
+
+ // 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).
+ var 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.
+ string message = string.Empty;
+ try
+ {
+ await _editTable.AddFeatureAsync(newFeature);
+ MessageTextBlock.Text = "New feature added to the '" + _editTable.TableName + "' table.";
+ }
+ catch (ArcGISException ex)
+ {
+ // Report the exception message.
+ MessageTextBlock.Text = ex.Message;
+ }
+ }
+ }
+
private async void StopEditTransaction(object sender, RoutedEventArgs e)
{
// Create a new dialog that prompts for commit, rollback, or cancel
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.jpg b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.jpg
new file mode 100644
index 0000000000..b29bd315bc
Binary files /dev/null and b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.jpg differ
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
new file mode 100644
index 0000000000..c27bb3efb6
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
new file mode 100644
index 0000000000..91ea2e9c3f
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
@@ -0,0 +1,408 @@
+// Copyright 2023 Esri.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
+// language governing permissions and limitations under the License.
+
+using Esri.ArcGISRuntime.Data;
+using Esri.ArcGISRuntime.Geometry;
+using Esri.ArcGISRuntime.Mapping;
+using Esri.ArcGISRuntime.Symbology;
+using Esri.ArcGISRuntime.UI;
+using Esri.ArcGISRuntime.UI.Controls;
+using Esri.ArcGISRuntime.UI.Editing;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using Windows.UI.Popups;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Geometry = Esri.ArcGISRuntime.Geometry.Geometry;
+using Symbol = Esri.ArcGISRuntime.Symbology.Symbol;
+
+namespace ArcGIS.UWP.Samples.CreateAndEditGeometries
+{
+ [ArcGIS.Samples.Shared.Attributes.Sample(
+ name: "Create and edit geometries",
+ category: "Geometry",
+ description: "Use the Geometry Editor to create new point, multipoint, polyline, or polygon geometries or to edit existing geometries by interacting with a map view.",
+ instructions: "To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).",
+ tags: new[] { "draw", "edit", "freehand", "geometry editor", "sketch", "vertex" })]
+ public partial class CreateAndEditGeometries
+ {
+ private GeometryEditor _geometryEditor;
+ private Graphic _selectedGraphic;
+ private GraphicsOverlay _graphicsOverlay;
+
+ private SimpleFillSymbol _polygonSymbol;
+ private SimpleLineSymbol _polylineSymbol;
+ private SimpleMarkerSymbol _pointSymbol, _multiPointSymbol;
+
+ private Dictionary _geometryButtons;
+ private Dictionary _toolDictionary;
+
+ // Json formatted strings for initial geometries.
+ private readonly string _houseCoordinatesJson = @"{""x"": -1067898.59, ""y"": 6998366.62,
+ ""spatialReference"": {""latestWkid"":3857, ""wkid"":102100}}";
+
+ private readonly string _outbuildingCoordinatesJson = @"{""points"":[[-1067984.26,6998346.28],[-1067966.80,6998244.84],
+ [-1067921.88,6998284.65],[-1067934.36,6998340.74],
+ [-1067917.93,6998373.97],[-1067828.30,6998355.28],
+ [-1067832.25,6998339.70],[-1067823.10,6998336.93],
+ [-1067873.22,6998386.78],[-1067896.72,6998244.49]],
+ ""spatialReference"":{""latestWkid"":3857,""wkid"":102100}}";
+
+ private readonly string _road1CoordinatesJson = @"{""paths"":[[[-1068095.40,6998123.52],[-1068086.16,6998134.60],
+ [-1068083.20,6998160.44],[-1068104.27,6998205.37],
+ [-1068070.63,6998255.22],[-1068014.44,6998291.54],
+ [-1067952.33,6998351.85],[-1067927.93,6998386.93],
+ [-1067907.97,6998396.78],[-1067889.86,6998406.63],
+ [-1067848.08,6998495.26],[-1067832.92,6998521.11]]],
+ ""spatialReference"":{""latestWkid"":3857,""wkid"":102100}}";
+
+ private readonly string _road2CoordinatesJson = @"{""paths"":[[[-1067999.28,6998061.97],[-1067994.48,6998086.59],
+ [-1067964.53,6998125.37],[-1067952.70,6998215.84],
+ [-1067923.13,6998347.54],[-1067903.90,6998391.86],
+ [-1067895.40,6998422.02],[-1067891.70,6998460.18],
+ [-1067889.49,6998483.56],[-1067880.98,6998527.26]]],
+ ""spatialReference"":{""latestWkid"":3857,""wkid"":102100}}";
+
+ private readonly string _boundaryCoordinatesJson = @"{ ""rings"": [[[-1067943.67,6998403.86],[-1067938.17,6998427.60],
+ [-1067898.77,6998415.86],[-1067888.26,6998398.80],
+ [-1067800.85,6998372.93],[-1067799.61,6998342.81],
+ [-1067809.38,6998330.00],[-1067817.07,6998307.85],
+ [-1067838.07,6998285.34],[-1067849.10,6998250.38],
+ [-1067874.02,6998256.00],[-1067879.87,6998235.95],
+ [-1067913.41,6998245.03],[-1067934.84,6998291.34],
+ [-1067948.41,6998251.90],[-1067961.18,6998186.68],
+ [-1068008.59,6998199.49],[-1068052.89,6998225.45],
+ [-1068039.37,6998261.11],[-1068064.12,6998265.26],
+ [-1068043.32,6998299.88],[-1068036.25,6998327.93],
+ [-1068004.43,6998409.28],[-1067943.67,6998403.86]]],
+ ""spatialReference"":{""latestWkid"":3857,""wkid"":102100}}";
+
+ public CreateAndEditGeometries()
+ {
+ InitializeComponent();
+ Initialize();
+ }
+
+ private void Initialize()
+ {
+ // Create a map for the map view and set an inital viewpoint.
+ MyMapView.Map = new Map(BasemapStyle.ArcGISImagery)
+ {
+ InitialViewpoint = new Viewpoint(53.08230, -9.5920, 5000)
+ };
+
+ // Create a graphics overlay and add it to the map view.
+ _graphicsOverlay = new GraphicsOverlay();
+ MyMapView.GraphicsOverlays.Add(_graphicsOverlay);
+
+ // Create a geometry editor and set it to the map view.
+ _geometryEditor = new GeometryEditor();
+ MyMapView.GeometryEditor = _geometryEditor;
+
+ // Create vertex and freehand tools for the combo box.
+ ToolComboBox.ItemsSource = _toolDictionary = new Dictionary()
+ {
+ { "Vertex Tool", new VertexTool() },
+ { "Reticle Vertex Tool", new ReticleVertexTool() },
+ { "Freehand Tool", new FreehandTool() },
+ { "Arrow Shape Tool", ShapeTool.Create(ShapeToolType.Arrow) },
+ { "Ellipse Shape Tool", ShapeTool.Create(ShapeToolType.Ellipse) },
+ { "Rectangle Shape Tool", ShapeTool.Create(ShapeToolType.Rectangle) },
+ { "Triangle Shape Tool", ShapeTool.Create(ShapeToolType.Triangle) }
+ };
+
+ // Have the vertex tool selected by default.
+ ToolComboBox.SelectedIndex = 0;
+
+ // Create a dictionary to lookup which geometry type corresponds with which button.
+ _geometryButtons = new Dictionary
+ {
+ { GeometryType.Point, PointButton },
+ { GeometryType.Multipoint, MultipointButton },
+ { GeometryType.Polyline, PolylineButton },
+ { GeometryType.Polygon, PolygonButton }
+ };
+
+ CreateInitialGraphics();
+ }
+
+ #region Event handlers
+ // Starts the geometry editor with the point geometry type.
+ private void PointButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (!_geometryEditor.IsStarted)
+ {
+ // Disable buttons to reflect that the geometry editor has started.
+ DisableOtherGeometryButtons(PointButton);
+
+ // Disable the combo box as this is always a vertex tool when creating a point.
+ ToolComboBox.IsEnabled = false;
+
+ // Disable scale checkbox since points don't scale.
+ UniformScaleCheckBox.IsEnabled = false;
+
+ _geometryEditor.Start(GeometryType.Point);
+ }
+ }
+
+ // Start the geometry editor with the multipoint geometry type.
+ private void MultipointButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (!_geometryEditor.IsStarted)
+ {
+ // Disable buttons to reflect that the geometry editor has started.
+ DisableOtherGeometryButtons(MultipointButton);
+
+ // Disable the combo box as this is always a vertex tool when creating a point.
+ ToolComboBox.IsEnabled = false;
+
+ _geometryEditor.Start(GeometryType.Multipoint);
+ }
+ }
+
+ // Start the geometry editor with the polyline geometry type.
+ private void PolylineButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (!_geometryEditor.IsStarted)
+ {
+ // Disable buttons to reflect that the geometry editor has started.
+ DisableOtherGeometryButtons(PolylineButton);
+
+ _geometryEditor.Start(GeometryType.Polyline);
+ }
+ }
+
+ // Start the geometry editor with the polygon geometry type.
+ private void PolygonButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (!_geometryEditor.IsStarted)
+ {
+ // Disable buttons to reflect that the geometry editor has started.
+ DisableOtherGeometryButtons(PolygonButton);
+
+ _geometryEditor.Start(GeometryType.Polygon);
+ }
+ }
+
+ // Set the geometry editor tool from the combo box.
+ private void ToolComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ // Set the geometry editor tool based on the new selection.
+ _geometryEditor.Tool = ((KeyValuePair)ToolComboBox.SelectedItem).Value as GeometryEditorTool;
+
+ // Account for case when vertex tool is selected and geometry editor is started with a polyline or polygon geometry type.
+ // Ensure point and multipoint buttons are only enabled when the selected tool is a vertex tool.
+ PointButton.IsEnabled = MultipointButton.IsEnabled = !_geometryEditor.IsStarted && _geometryEditor.Tool is VertexTool;
+
+ // Uniform scale is not compatible with the reticle vertex tool.
+ UniformScaleCheckBox.IsEnabled = !(_geometryEditor.Tool is ReticleVertexTool);
+ }
+
+ // Set the scale mode for every geometry editor tool.
+ private void CheckBox_CheckedChanged(object sender, RoutedEventArgs e)
+ {
+ // Determine the newly selected scale mode.
+ GeometryEditorScaleMode scaleMode =
+ UniformScaleCheckBox.IsChecked == true ? GeometryEditorScaleMode.Uniform : GeometryEditorScaleMode.Stretch;
+
+ // Update the scale mode for every tool.
+ foreach (GeometryEditorTool tool in _toolDictionary.Values)
+ {
+ if (tool is FreehandTool freehandTool)
+ {
+ freehandTool.Configuration.ScaleMode = scaleMode;
+ }
+ else if (tool is VertexTool vertexTool)
+ {
+ vertexTool.Configuration.ScaleMode = scaleMode;
+ }
+ else if (tool is ShapeTool shapeTool)
+ {
+ shapeTool.Configuration.ScaleMode = scaleMode;
+ }
+ }
+ }
+
+ // Undo the last change made to the geometry while editing is active.
+ private void UndoButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.Undo();
+ }
+
+ // Redo the last change made to the geometry while editing is active.
+ private void RedoButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.Redo();
+ }
+
+ // Delete the currently selected element of the geometry editor.
+ private void DeleteSelectedButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.DeleteSelectedElement();
+ }
+
+ // Update an existing graphic or create a new graphic.
+ private void SaveButton_Click(object sender, RoutedEventArgs e)
+ {
+ Geometry geometry = _geometryEditor.Stop();
+
+ if (geometry != null)
+ {
+ if (_selectedGraphic != null)
+ {
+ // Update the geometry of the graphic being edited and make it visible again.
+ _selectedGraphic.Geometry = geometry;
+ }
+ else
+ {
+ // Create a new graphic based on the geometry and add it to the graphics overlay.
+ _graphicsOverlay.Graphics.Add(new Graphic(geometry, GetSymbol(geometry.GeometryType)));
+ }
+ }
+
+ ResetFromEditingSession();
+ }
+
+ // Stop the geometry editor without saving the geometry stored within.
+ private void DiscardButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.Stop();
+ ResetFromEditingSession();
+ }
+
+ // Removes all graphics from the graphics overlay.
+ private void DeleteAllButton_Click(object sender, RoutedEventArgs e)
+ {
+ _graphicsOverlay.Graphics.Clear();
+ }
+
+ private async void MyMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e)
+ {
+ // Return immediately when in an editing session.
+ if (_geometryEditor.IsStarted) return;
+
+ try
+ {
+ // Identify graphics in the graphics overlay using the mouse point.
+ IReadOnlyList results = await MyMapView.IdentifyGraphicsOverlaysAsync(e.Position, 5, false);
+
+ // Try to get the first graphic from the first result.
+ _selectedGraphic = results.FirstOrDefault()?.Graphics?.FirstOrDefault();
+ }
+ catch (Exception ex)
+ {
+ // Report exceptions.
+ await new MessageDialog(e.ToString(), "Error").ShowAsync();
+
+ ResetFromEditingSession();
+ return;
+ }
+
+ // Return since no graphic was selected.
+ if (_selectedGraphic == null) return;
+
+ _selectedGraphic.IsSelected = true;
+
+ // Configure the UI depending on the geometry type.
+ GeometryType geometryType = _selectedGraphic.Geometry.GeometryType;
+ if (geometryType == GeometryType.Point)
+ {
+ ToolComboBox.SelectedIndex = 0;
+ UniformScaleCheckBox.IsEnabled = false;
+ }
+ if (geometryType == GeometryType.Multipoint)
+ {
+ ToolComboBox.SelectedIndex = 0;
+ }
+ DisableOtherGeometryButtons(_geometryButtons[geometryType]);
+
+ // Hide the selected graphic and start an editing session with a copy of it.
+ _geometryEditor.Start(_selectedGraphic.Geometry);
+ _selectedGraphic.IsVisible = false;
+ }
+ #endregion
+
+ #region Helper methods
+ private void CreateInitialGraphics()
+ {
+ // Create symbols for displaying new geometries.
+ _pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Square, Color.OrangeRed, 10);
+ _multiPointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Yellow, 5);
+ _polylineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.Blue, 2);
+ var polygonLineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Dash, Color.Black, 1);
+ _polygonSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Color.FromArgb(70, 255, 0, 0), polygonLineSymbol);
+
+ // Create geometries from Json formatted strings.
+ var houseCoordinates = (MapPoint)Geometry.FromJson(_houseCoordinatesJson);
+ var outbuildingCoordinates = (Multipoint)Geometry.FromJson(_outbuildingCoordinatesJson);
+ var road1Coordinates = (Polyline)Geometry.FromJson(_road1CoordinatesJson);
+ var road2Coordinates = (Polyline)Geometry.FromJson(_road2CoordinatesJson);
+ var boundaryCoordinates = (Polygon)Geometry.FromJson(_boundaryCoordinatesJson);
+
+ // Add new example graphics from the geometries and symbols to the graphics overlay.
+ _graphicsOverlay.Graphics.Add(new Graphic(houseCoordinates) { Symbol = _pointSymbol });
+ _graphicsOverlay.Graphics.Add(new Graphic(outbuildingCoordinates) { Symbol = _multiPointSymbol });
+ _graphicsOverlay.Graphics.Add(new Graphic(road1Coordinates) { Symbol = _polylineSymbol });
+ _graphicsOverlay.Graphics.Add(new Graphic(road2Coordinates) { Symbol = _polylineSymbol });
+ _graphicsOverlay.Graphics.Add(new Graphic(boundaryCoordinates) { Symbol = _polygonSymbol });
+ }
+
+ // Reset the UI after the editor stops.
+ private void ResetFromEditingSession()
+ {
+ // Reset the selected graphic.
+ if (_selectedGraphic != null)
+ {
+ _selectedGraphic.IsSelected = false;
+ _selectedGraphic.IsVisible = true;
+ }
+ _selectedGraphic = null;
+
+ // Point and multipoint sessions do not support the vertex tool.
+ PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool || _geometryEditor.Tool is ReticleVertexTool;
+ PolylineButton.IsEnabled = PolygonButton.IsEnabled = true;
+ ToolComboBox.IsEnabled = true;
+
+ UniformScaleCheckBox.IsEnabled = true;
+ }
+
+ // Return the graphic style based on geometry type.
+ private Symbol GetSymbol(GeometryType geometryType)
+ {
+ switch (geometryType)
+ {
+ case GeometryType.Point:
+ return _pointSymbol;
+
+ case GeometryType.Multipoint:
+ return _multiPointSymbol;
+
+ case GeometryType.Polyline:
+ return _polylineSymbol;
+
+ case GeometryType.Polygon:
+ return _polygonSymbol;
+ }
+ return null;
+ }
+
+ // Disable all geometry buttons besides the one that was just clicked.
+ private void DisableOtherGeometryButtons(Button keepEnabled)
+ {
+ foreach (Button button in _geometryButtons.Values)
+ {
+ button.IsEnabled = button == keepEnabled;
+ }
+ }
+
+ #endregion Helper methods
+ }
+}
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
new file mode 100644
index 0000000000..85816c070d
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
@@ -0,0 +1,51 @@
+# Create and edit geometries
+
+Use the Geometry Editor to create new point, multipoint, polyline, or polygon geometries or to edit existing geometries by interacting with a map view.
+
+![CreateAndEditGeometries](CreateAndEditGeometries.jpg)
+
+## Use case
+
+A field worker can mark features of interest on a map using an appropriate geometry. Features such as sample or observation locations, fences or pipelines, and building footprints can be digitized using point, multipoint, polyline, and polygon geometry types. Polyline and polygon geometries can be created and edited using a vertex-based creation and editing tool (i.e. vertex locations specified explicitly via tapping), or using a freehand tool.
+
+## How to use the sample
+
+To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).
+
+Use the control panel to undo or redo changes made to the geometry, delete a selected element, save the geometry, stop the editing session and discard any edits, and remove all geometries from the map.
+
+## How it works
+
+1. Create a `GeometryEditor` and set it to the MapView using `MyMapView.GeometryEditor`.
+2. Start the `GeometryEditor` using `GeometryEditor.Start(GeometryType)` to create a new geometry or `GeometryEditor.Start(Geometry)` to edit an existing geometry.
+ * If using the Geometry Editor to edit an existing geometry, the geometry must be retrieved from the graphics overlay being used to visualize the geometry prior to calling the start method. To do this:
+ * Use `MapView.IdentifyGraphicsOverlayAsync(...)` to identify graphics at the location of a tap.
+ * Access the `MapView.IdentifyGraphicsOverlayAsync(...)`.
+ * Find the desired graphic in the `results.FirstOrDefault()` list.
+ * Access the geometry associated with the `Graphic` using `Graphic.Geometry` - this will be used in the `GeometryEditor.Start(Geometry)` method.
+3. Create `VertexTool`, `FreehandTool`, or `ShapeTool` objects which define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
+4. Edit a tool's InteractionConfiguration to set the GeometryEditorScaleMode to allow either uniform or stretch scale mode.
+5. Check to see if undo and redo are possible during an editing session using `GeometryEditor.CanUndo` and `GeometryEditor.CanRedo`. If it's possible, use `GeometryEditor.Undo()` and `GeometryEditor.Redo()`.
+6. Check whether the currently selected `GeometryEditorElement` can be deleted (`GeometryEditor.SelectedElement.CanDelete`). If the element can be deleted, delete using `GeometryEditor.DeleteSelectedElement()`.
+7. Call `GeometryEditor.Stop()` to finish the editing session and store the `Graphic`. The `GeometryEditor` does not automatically handle the visualization of a geometry output from an editing session. This must be done manually by propagating the geometry returned into a `Graphic` added to a `GraphicsOverlay`.
+ * To create a new `Graphic` in the `GraphicsOverlay`:
+ * Using `Graphic(Geometry)`, create a new Graphic with the geometry returned by the `GeometryEditor.Stop()` method.
+ * Append the `Graphic` to the `GraphicsOverlay`(i.e. `GraphicsOverlay.Graphics.Add(Graphic)`).
+ * To update the geometry underlying an existing `Graphic` in the `GraphicsOverlay`:
+ * Replace the existing `Graphic`'s `Geometry` property with the geometry returned by the `GeometryEditor.Stop()` method.
+
+## Relevant API
+
+* Geometry
+* GeometryEditor
+* Graphic
+* GraphicsOverlay
+* MapView
+
+## Additional information
+
+The sample opens with the ArcGIS Imagery basemap centered on the island of Inis Meain (Aran Islands) in Ireland. Inis Meain comprises a landscape of interlinked stone walls, roads, buildings, archaeological sites, and geological features, producing complex geometrical relationships.
+
+## Tags
+
+draw, edit, freehand, geometry editor, sketch, vertex
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.metadata.json b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.metadata.json
new file mode 100644
index 0000000000..76b25892e3
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.metadata.json
@@ -0,0 +1,33 @@
+{
+ "category": "Geometry",
+ "description": "Use the Geometry Editor to create new point, multipoint, polyline, or polygon geometries or to edit existing geometries by interacting with a map view.",
+ "formal_name": "CreateAndEditGeometries",
+ "ignore": false,
+ "images": [
+ "CreateAndEditGeometries.jpg"
+ ],
+ "keywords": [
+ "draw",
+ "edit",
+ "freehand",
+ "geometry editor",
+ "sketch",
+ "vertex"
+ ],
+ "offline_data": [],
+ "redirect_from": [
+ "/net/latest/uwp/sample-code/create-and-edit-geometries.htm"
+ ],
+ "relevant_apis": [
+ "Geometry",
+ "GeometryEditor",
+ "Graphic",
+ "GraphicsOverlay",
+ "MapView"
+ ],
+ "snippets": [
+ "CreateAndEditGeometries.xaml.cs",
+ "CreateAndEditGeometries.xaml"
+ ],
+ "title": "Create and edit geometries"
+}
\ No newline at end of file
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg
new file mode 100644
index 0000000000..51bcd7468d
Binary files /dev/null and b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg differ
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
new file mode 100644
index 0000000000..f361b0de4b
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
new file mode 100644
index 0000000000..1bd668ce90
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
@@ -0,0 +1,410 @@
+// Copyright 2024 Esri.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
+// language governing permissions and limitations under the License.
+
+using Esri.ArcGISRuntime.UI.Editing;
+using Esri.ArcGISRuntime.UI;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+using Esri.ArcGISRuntime.Data;
+using Esri.ArcGISRuntime.Geometry;
+using Esri.ArcGISRuntime.Mapping;
+using Esri.ArcGISRuntime.UI.Controls;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using Windows.UI.Popups;
+using Geometry = Esri.ArcGISRuntime.Geometry.Geometry;
+
+namespace ArcGIS.UWP.Samples.SnapGeometryEdits
+{
+ [ArcGIS.Samples.Shared.Attributes.Sample(
+ name: "Snap geometry edits",
+ category: "Geometry",
+ description: "Use the Geometry Editor to edit a geometry and align it to existing geometries on a map.",
+ instructions: "To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.",
+ tags: new[] { "edit", "feature", "geometry editor", "graphics", "layers", "map", "snapping" })]
+ public partial class SnapGeometryEdits
+ {
+ // Hold references for use in event handlers.
+ private GeometryEditor _geometryEditor;
+ private GraphicsOverlay _graphicsOverlay;
+ private Graphic _selectedGraphic;
+ private List _geometryEditorToolButtons;
+
+ public SnapGeometryEdits()
+ {
+ InitializeComponent();
+ _ = Initialize();
+ }
+
+ private async Task Initialize()
+ {
+ // Create a map using a Uri.
+ var myMap = new Map(new Uri("https://www.arcgis.com/home/item.html?id=b95fe18073bc4f7788f0375af2bb445e"));
+
+ // Set the map load setting feature tiling mode.
+ // Enabled with full resolution when supported is used to ensure that snapping to geometries occurs in full resolution.
+ // Snapping in full resolution improves snapping accuracy.
+ myMap.LoadSettings.FeatureTilingMode = FeatureTilingMode.EnabledWithFullResolutionWhenSupported;
+
+ // Set the initial viewpoint.
+ myMap.InitialViewpoint = new Viewpoint(new MapPoint(-9812798, 5126406, SpatialReferences.WebMercator), 2000);
+
+ // Create a graphics overlay and add it to the map view.
+ _graphicsOverlay = new GraphicsOverlay();
+ MyMapView.GraphicsOverlays.Add(_graphicsOverlay);
+
+ // Add the map to the map view.
+ MyMapView.Map = myMap;
+
+ // Create and add a geometry editor to the map view.
+ _geometryEditor = new GeometryEditor();
+ MyMapView.GeometryEditor = _geometryEditor;
+
+ // Load the map.
+ await myMap.LoadAsync();
+
+ // Ensure all layers are loaded before setting the snap settings.
+ // If this is not awaited there is a risk that operational layers may not have loaded and therefore would not have been included in the snap sources.
+ await Task.WhenAll(MyMapView.Map.OperationalLayers.ToList().Select(layer => layer.LoadAsync()).ToList());
+
+ // Set the snap source settings.
+ SetSnapSettings();
+
+ // Show the UI.
+ SnappingControls.Visibility = Visibility.Visible;
+
+ // Store a reference to the geometry editor tool buttons to update their background color when selected.
+ _geometryEditorToolButtons = new List()
+ {
+ PointButton,
+ PolylineButton,
+ PolygonButton,
+ MultipointButton
+ };
+
+ // Add an event handler to detect geoview tapped events.
+ MyMapView.GeoViewTapped += MyMapView_GeoViewTapped;
+ }
+
+ private void SetSnapSettings()
+ {
+ // Synchronize the snap source collection with the map's operational layers.
+ // Note that layers that have not been loaded will not synchronize.
+ _geometryEditor.SnapSettings.SyncSourceSettings();
+
+ // Enable snapping on the geometry layer.
+ _geometryEditor.SnapSettings.IsEnabled = true;
+
+ // Create a list of snap source settings with snapping disabled.
+ List snapSourceSettingsVMs = _geometryEditor.SnapSettings.SourceSettings.Select(sourceSettings => new SnapSourceSettingsVM(sourceSettings) { IsEnabled = false }).ToList();
+
+ // Populate lists of snap source settings for point and polyline layers.
+ PointSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Point).ToList();
+ PolylineSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Polyline).ToList();
+
+ // Populate a list of snap source settings for graphics overlays.
+ GraphicsOverlaySnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingsVM => snapSourceSettingsVM.SnapSourceSettings.Source is GraphicsOverlay).ToList();
+ }
+
+ private void CreateNewGraphic()
+ {
+ // Get the new geometry from the geometry editor.
+ Geometry geometry = _geometryEditor.Stop();
+
+ // Create a graphic.
+ var graphic = new Graphic(geometry);
+
+ // Create a geometry editor style to get symbols for the new graphic.
+ var geometryEditorStyle = new GeometryEditorStyle();
+
+ switch (geometry.GeometryType)
+ {
+ case GeometryType.Point:
+ graphic.Symbol = geometryEditorStyle.VertexSymbol;
+ break;
+ case GeometryType.Envelope:
+ graphic.Symbol = geometryEditorStyle.LineSymbol;
+ break;
+ case GeometryType.Polyline:
+ graphic.Symbol = geometryEditorStyle.LineSymbol;
+ break;
+ case GeometryType.Polygon:
+ graphic.Symbol = geometryEditorStyle.FillSymbol;
+ break;
+ case GeometryType.Multipoint:
+ graphic.Symbol = geometryEditorStyle.VertexSymbol;
+ break;
+ }
+
+ // Add the graphic to the GraphicsOverlay and unselect it.
+ _graphicsOverlay.Graphics.Add(graphic);
+ graphic.IsSelected = false;
+ }
+
+ private async void MyMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e)
+ {
+ // If the geometry editor is active then stop.
+ if (_geometryEditor.IsStarted) return;
+
+ try
+ {
+ // Get the list of identified graphics overlay results based on tap position.
+ IReadOnlyList results = await MyMapView.IdentifyGraphicsOverlaysAsync(e.Position, 10, false);
+
+ // If a graphics overlay result has been tapped and contains a corresponding graphic,
+ // set the selected graphic and start the geometry editor.
+ if (results.Any() && results[0].Graphics.Any())
+ {
+ _selectedGraphic = results[0].Graphics[0];
+ _selectedGraphic.IsSelected = true;
+ }
+ else
+ {
+ // No results have been found, update the selected graphic.
+ _selectedGraphic = null;
+ }
+ }
+ catch (Exception ex)
+ {
+ await new MessageDialog(ex.Message).ShowAsync();
+
+ // Reset the UI.
+ ResetFromEditingSession();
+ return;
+ }
+
+ if (_selectedGraphic == null) return;
+
+ // Hide the selected graphic and start an editing session with a copy of it.
+ _geometryEditor.Start(_selectedGraphic.Geometry);
+ _selectedGraphic.IsVisible = false;
+ }
+
+ // Reset the UI after the editor stops.
+ private void ResetFromEditingSession()
+ {
+ // Reset the selected graphic.
+ if (_selectedGraphic != null)
+ {
+ _selectedGraphic.IsSelected = false;
+ _selectedGraphic.IsVisible = true;
+ }
+
+ foreach (var toggleButton in _geometryEditorToolButtons)
+ {
+ toggleButton.IsChecked = false;
+ }
+
+ _selectedGraphic = null;
+ }
+
+ #region Enable Sources Button Handlers
+ // Enable all point layer snap sources.
+ private void EnableAllPointSnapSourceButton_Click(object sender, RoutedEventArgs e)
+ {
+ foreach (var item in PointSnapSettingsList.Items.ToList())
+ {
+ if (item is SnapSourceSettingsVM snapSourceSettingsVM)
+ {
+ snapSourceSettingsVM.IsEnabled = true;
+ }
+ }
+ }
+
+ // Enable all polyline layer snap sources.
+ private void EnableAllPolylineSnapSourceButton_Click(object sender, RoutedEventArgs e)
+ {
+ foreach (var item in PolylineSnapSettingsList.Items.ToList())
+ {
+ if (item is SnapSourceSettingsVM snapSourceSettingsVM)
+ {
+ snapSourceSettingsVM.IsEnabled = true;
+ }
+ }
+ }
+ #endregion
+
+ #region Geometry Management Button Handlers
+ private void DeleteButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.DeleteSelectedElement();
+ }
+
+ private void UndoButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.Undo();
+ }
+
+ private void SaveButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_selectedGraphic?.Geometry != null)
+ {
+ _selectedGraphic.Geometry = _geometryEditor.Stop();
+ _selectedGraphic.IsSelected = false;
+ }
+ else if (_geometryEditor.IsStarted)
+ {
+ CreateNewGraphic();
+ }
+
+ ResetFromEditingSession();
+ }
+
+ private void DiscardButton_Click(object sender, RoutedEventArgs e)
+ {
+ _geometryEditor.Stop();
+
+ ResetFromEditingSession();
+ }
+ #endregion
+
+ #region Geometry Tool Buttons Handlers
+ private void ReticleVertexToolCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
+ {
+ if (ReticleVertexToolCheckBox.IsChecked == true)
+ {
+ _geometryEditor.Tool = new ReticleVertexTool();
+ }
+ else
+ {
+ _geometryEditor.Tool = new VertexTool();
+ }
+ }
+
+ private void PointButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_geometryEditor.IsStarted)
+ {
+ _geometryEditor.Stop();
+ }
+
+ ResetFromEditingSession();
+
+ PointButton.IsChecked = true;
+ _geometryEditor.Start(GeometryType.Point);
+ }
+
+ private void MultipointButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_geometryEditor.IsStarted)
+ {
+ _geometryEditor.Stop();
+ }
+
+ ResetFromEditingSession();
+
+ MultipointButton.IsChecked = true;
+ _geometryEditor.Start(GeometryType.Multipoint);
+ }
+ private void PolylineButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_geometryEditor.IsStarted)
+ {
+ _geometryEditor.Stop();
+ }
+
+ ResetFromEditingSession();
+
+ PolylineButton.IsChecked = true;
+ _geometryEditor.Start(GeometryType.Polyline);
+ }
+ private void PolygonButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (_geometryEditor.IsStarted)
+ {
+ _geometryEditor.Stop();
+ }
+
+ ResetFromEditingSession();
+
+ PolygonButton.IsChecked = true;
+ _geometryEditor.Start(GeometryType.Polygon);
+ }
+ #endregion
+ }
+
+ public class SnapSourceSettingsVM : INotifyPropertyChanged
+ {
+ public SnapSourceSettings SnapSourceSettings { get; set; }
+
+ // Wrap the snap source settings in a view model to expose them to the UI.
+ public SnapSourceSettingsVM(SnapSourceSettings snapSourceSettings)
+ {
+ SnapSourceSettings = snapSourceSettings;
+
+ if (snapSourceSettings.Source is FeatureLayer featureLayer)
+ {
+ Name = featureLayer.Name;
+
+ if (featureLayer.FeatureTable != null)
+ {
+ GeometryType = featureLayer.FeatureTable.GeometryType;
+ }
+ }
+ else if (snapSourceSettings.Source is GraphicsOverlay graphicsOverlay)
+ {
+ Name = "Editor graphics overlay";
+ }
+
+ IsEnabled = snapSourceSettings.IsEnabled;
+ }
+
+ private string _name;
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ set
+ {
+ _name = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isEnabled;
+ public bool IsEnabled
+ {
+ get
+ {
+ return _isEnabled;
+ }
+ set
+ {
+ _isEnabled = value;
+ SnapSourceSettings.IsEnabled = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public GeometryType GeometryType { get; set; }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ var handler = PropertyChanged;
+ if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
new file mode 100644
index 0000000000..87c86309b8
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
@@ -0,0 +1,62 @@
+# Snap geometry edits
+
+Use the Geometry Editor to edit a geometry and align it to existing geometries on a map.
+
+![Image of Snap geometry edits](SnapGeometryEdits.jpg)
+
+## Use case
+
+A field worker can create new features by editing and snapping the vertices of a geometry to existing features on a map. In a water distribution network, service line features can be represented with the polyline geometry type. By snapping the vertices of a proposed service line to existing features in the network, an exact footprint can be identified to show the path of the service line and what features in the network it connects to. The feature layer containing the service lines can then be accurately modified to include the proposed line.
+
+## How to use the sample
+
+To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.
+
+To configure snapping, press the snap settings button to enable or disable snapping and choose which snap sources to snap to.
+
+To interactively snap a vertex to a feature or graphic, ensure that snapping is enabled for the relevant snap source and move the mouse pointer or drag a vertex to nearby an existing feature or graphic. When the pointer is close to that existing geoelement, the edit position will be adjusted to coincide with (or snap to), edges and vertices of its geometry. Click or release the touch pointer to place the vertex at the snapped location.
+
+To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features or graphics.
+
+To undo changes made to the geometry, press the undo button.
+
+To delete a geometry or a vertex, tap the geometry or vertex to select it and then press the delete button.
+
+To save your edits, press the save button.
+
+## How it works
+
+1. Create a `Map` from the `URL` and connect it to the `MapView`.
+2. Set the map's `LoadSettings.FeatureTilingMode` to `EnabledWithFullResolutionWhenSupported`.
+3. Create a `GeometryEditor` and connect it to the map view.
+4. Call `SyncSourceSettings` after the map's operational layers are loaded and the geometry editor has connected to the map view.
+5. Set `SnapSettings.IsEnabled` and `SnapSourceSettings.IsEnabled` to true for the `SnapSource` of interest.
+6. Start the geometry editor with a `GeometryType`.
+
+## Relevant API
+
+* FeatureLayer
+* Geometry
+* GeometryEditor
+* GeometryEditorStyle
+* GraphicsOverlay
+* MapView
+* SnapSettings
+* SnapSource
+* SnapSourceSettings
+
+## About the data
+
+The [Naperville water distribution network](https://www.arcgis.com/home/item.html?id=b95fe18073bc4f7788f0375af2bb445e) is based on ArcGIS Solutions for Water Utilities and provides a realistic depiction of a theoretical stormwater network.
+
+## Additional information
+
+Snapping is used to maintain data integrity between different sources of data when editing, so it is important that each `SnapSource` provides full resolution geometries to be valid for snapping. This means that some of the default optimizations used to improve the efficiency of data transfer and display of polygon and polyline layers based on feature services are not appropriate for use with snapping.
+
+To snap to polygon and polyline layers, the recommended approach is to set the `FeatureLayer`'s feature tiling mode to `FeatureTilingMode.EnabledWithFullResolutionWhenSupported` and use the default `ServiceFeatureTable` feature request mode `FeatureRequestMode.OnInteractionCache`. Local data sources, such as geodatabases, always provide full resolution geometries. Point and multipoint feature layers are also always full resolution.
+
+Snapping can be used during interactive edits that move existing vertices using the `VertexTool` or `ReticleVertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the `ReticleVertexTool` to add and move vertices allows users of touch screen devices to clearly see the visual cues for snapping.
+
+## Tags
+
+edit, feature, geometry editor, graphics, layers, map, snapping
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
new file mode 100644
index 0000000000..df4eaa76cd
--- /dev/null
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
@@ -0,0 +1,38 @@
+{
+ "category": "Geometry",
+ "description": "Use the Geometry Editor to edit a geometry and align it to existing geometries on a map.",
+ "formal_name": "SnapGeometryEdits",
+ "ignore": false,
+ "images": [
+ "SnapGeometryEdits.jpg"
+ ],
+ "keywords": [
+ "edit",
+ "feature",
+ "geometry editor",
+ "graphics",
+ "layers",
+ "map",
+ "snapping"
+ ],
+ "offline_data": [],
+ "redirect_from": [
+ "/net/latest/uwp/sample-code/snap-geometry-edits.htm"
+ ],
+ "relevant_apis": [
+ "FeatureLayer",
+ "Geometry",
+ "GeometryEditor",
+ "GeometryEditorStyle",
+ "GraphicsOverlay",
+ "MapView",
+ "SnapSettings",
+ "SnapSource",
+ "SnapSourceSettings"
+ ],
+ "snippets": [
+ "SnapGeometryEdits.xaml.cs",
+ "SnapGeometryEdits.xaml"
+ ],
+ "title": "Snap geometry edits"
+}
\ No newline at end of file
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.jpg b/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.jpg
deleted file mode 100644
index 52b9c8985e..0000000000
Binary files a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.jpg and /dev/null differ
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.xaml b/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.xaml
deleted file mode 100644
index 72448f32ba..0000000000
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.xaml
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.xaml.cs b/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.xaml.cs
deleted file mode 100644
index 41341d71ad..0000000000
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/SketchOnMap.xaml.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2017 Esri.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
-// language governing permissions and limitations under the License.
-
-using Esri.ArcGISRuntime.Data;
-using Esri.ArcGISRuntime.Geometry;
-using Esri.ArcGISRuntime.Mapping;
-using Esri.ArcGISRuntime.Symbology;
-using Esri.ArcGISRuntime.UI;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Drawing;
-using Windows.UI.Popups;
-using Windows.UI.Xaml;
-
-namespace ArcGIS.UWP.Samples.SketchOnMap
-{
- [ArcGIS.Samples.Shared.Attributes.Sample(
- name: "Sketch on map",
- category: "GraphicsOverlay",
- description: "Use the Sketch Editor to edit or sketch a new point, line, or polygon geometry on to a map.",
- instructions: "Choose which geometry type to sketch from one of the available buttons. Choose from points, multipoints, polylines, polygons, freehand polylines, and freehand polygons.",
- tags: new[] { "draw", "edit" })]
- public sealed partial class SketchOnMap
- {
- // Graphics overlay to host sketch graphics
- private GraphicsOverlay _sketchOverlay;
-
- public SketchOnMap()
- {
- InitializeComponent();
-
- // Call a function to set up the map and sketch editor
- Initialize();
- }
-
- private void Initialize()
- {
- // Create a light gray canvas map
- Map myMap = new Map(BasemapStyle.ArcGISLightGray);
-
- // Create graphics overlay to display sketch geometry
- _sketchOverlay = new GraphicsOverlay();
- MyMapView.GraphicsOverlays.Add(_sketchOverlay);
-
- // Assign the map to the MapView
- MyMapView.Map = myMap;
-
- // Fill the combo box with choices for the sketch modes (shapes)
- SketchModeComboBox.ItemsSource = System.Enum.GetValues(typeof(SketchCreationMode));
- SketchModeComboBox.SelectedIndex = 0;
-
- // Set the sketch editor as the page's data context
- DataContext = MyMapView.SketchEditor;
- }
-
- #region Graphic and symbol helpers
- private Graphic CreateGraphic(Esri.ArcGISRuntime.Geometry.Geometry geometry)
- {
- // Create a graphic to display the specified geometry
- Symbol symbol = null;
- switch (geometry.GeometryType)
- {
- // Symbolize with a fill symbol
- case GeometryType.Envelope:
- case GeometryType.Polygon:
- {
- symbol = new SimpleFillSymbol()
- {
- Color = Color.Red,
- Style = SimpleFillSymbolStyle.Solid
- };
- break;
- }
- // Symbolize with a line symbol
- case GeometryType.Polyline:
- {
- symbol = new SimpleLineSymbol()
- {
- Color = Color.Red,
- Style = SimpleLineSymbolStyle.Solid,
- Width = 5d
- };
- break;
- }
- // Symbolize with a marker symbol
- case GeometryType.Point:
- case GeometryType.Multipoint:
- {
-
- symbol = new SimpleMarkerSymbol()
- {
- Color = Color.Red,
- Style = SimpleMarkerSymbolStyle.Circle,
- Size = 15d
- };
- break;
- }
- }
-
- // pass back a new graphic with the appropriate symbol
- return new Graphic(geometry, symbol);
- }
-
- private async Task GetGraphicAsync()
- {
- // Wait for the user to click a location on the map
- MapPoint mapPoint = (MapPoint)await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Point, false);
-
- // Convert the map point to a screen point
- var screenCoordinate = MyMapView.LocationToScreen(mapPoint);
-
- // Identify graphics in the graphics overlay using the point
- IReadOnlyList results = await MyMapView.IdentifyGraphicsOverlaysAsync(screenCoordinate, 2, false);
-
- // If results were found, get the first graphic
- Graphic graphic = null;
- IdentifyGraphicsOverlayResult idResult = results.FirstOrDefault();
- if (idResult != null && idResult.Graphics.Count > 0)
- {
- graphic = idResult.Graphics.FirstOrDefault();
- }
-
- // Return the graphic (or null if none were found)
- return graphic;
- }
- #endregion
-
- 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 = (SketchCreationMode)SketchModeComboBox.SelectedItem;
- 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
- MessageDialog dialog = new MessageDialog("Error drawing graphic shape: " + ex.Message);
- await dialog.ShowAsync();
- }
- }
-
- private void ClearButtonClick(object sender, RoutedEventArgs e)
- {
- // Remove all graphics from the graphics overlay
- _sketchOverlay.Graphics.Clear();
-
- // Cancel any uncompleted sketch
- if (MyMapView.SketchEditor.CancelCommand.CanExecute(null))
- {
- MyMapView.SketchEditor.CancelCommand.Execute(null);
- }
-
- // Disable buttons that require graphics
- ClearButton.IsEnabled = false;
- EditButton.IsEnabled = false;
- }
-
- 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
- MessageDialog dialog = new MessageDialog("Error editing shape: " + ex.Message);
- await dialog.ShowAsync();
- }
- }
- }
-}
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/readme.md b/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/readme.md
deleted file mode 100644
index c6d1ca632c..0000000000
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/readme.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Sketch on map
-
-Use the Sketch Editor to edit or sketch a new point, line, or polygon geometry on to a map.
-
-![Image of sketch on map](SketchOnMap.jpg)
-
-## Use case
-
-A field worker could annotate features of interest on a map (via the GUI) such as location of dwellings (marked as points), geological features (polylines), or areas of glaciation (polygons).
-
-## How to use the sample
-
-Choose which geometry type to sketch from one of the available buttons. Choose from points, multipoints, polylines, polygons, freehand polylines, and freehand polygons.
-
-Use the control panel to cancel the sketch, undo or redo changes made to the sketch and to save the sketch to the graphics overlay. There is also the option to select a saved graphic and edit its geometry using the Sketch Editor. The graphics overlay can be cleared using the clear all button.
-
-## How it works
-
-1. Use `SketchEditor.StartAsync()` to start sketching. If editing an existing graphic's geometry, use `SketchEditor.StartAsync(graphic.Geometry)`.
-2. Use the `UndoCommand` and `RedoCommand` to undo and redo edits in the sketch.
-3. Use a `CompleteCommand` to finish the sketch and get the `Geometry` result. Use the `CancelCommand` to cancel the sketch.
-4. Create a `Graphic` for the geometry and add it to the `GraphicsOverlay` in the map view.
-
-## Relevant API
-
-* Geometry
-* Graphic
-* GraphicsOverlay
-* MapView
-* SketchCreationMode
-* SketchEditor
-
-## Tags
-
-draw, edit
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/readme.metadata.json b/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/readme.metadata.json
deleted file mode 100644
index 5c1fbcb529..0000000000
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/GraphicsOverlay/SketchOnMap/readme.metadata.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "category": "GraphicsOverlay",
- "description": "Use the Sketch Editor to edit or sketch a new point, line, or polygon geometry on to a map.",
- "formal_name": "SketchOnMap",
- "ignore": false,
- "images": [
- "SketchOnMap.jpg"
- ],
- "keywords": [
- "draw",
- "edit"
- ],
- "offline_data": [],
- "redirect_from": [
- "/net/latest/uwp/sample-code/sketchonmap.htm"
- ],
- "relevant_apis": [
- "Geometry",
- "Graphic",
- "GraphicsOverlay",
- "MapView",
- "SketchCreationMode",
- "SketchEditor"
- ],
- "snippets": [
- "SketchOnMap.xaml",
- "SketchOnMap.xaml.cs"
- ],
- "title": "Sketch on map"
-}
\ No newline at end of file
diff --git a/src/UWP/ArcGIS.UWP.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs b/src/UWP/ArcGIS.UWP.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs
index 503c231de0..9bbeb72f4b 100644
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/Layers/CreateAndSaveKmlFile/CreateAndSaveKmlFile.xaml.cs
@@ -13,6 +13,7 @@
using Esri.ArcGISRuntime.UI;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
@@ -37,6 +38,7 @@ public partial class CreateAndSaveKmlFile
private KmlDataset _kmlDataset;
private KmlLayer _kmlLayer;
private KmlPlacemark _currentPlacemark;
+ private GeometryType _geometryType;
public CreateAndSaveKmlFile()
{
@@ -97,26 +99,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 +124,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 = GeometryEngine.Project(geometry, 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);
+ // Start the geometry editor.
+ MyMapView.GeometryEditor.Start(_geometryType);
- // 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 MessageDialog("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 +180,59 @@ 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();
+
+ // Hold a reference for the new placemark geometry.
+ KmlGeometry kmlGeometry;
+
+ // Check to see if a geometry has been drawn.
+ if (!geometry.IsEmpty)
+ {
+
+ if (MyMapView.SpatialReference != null &&
+ geometry.SpatialReference != MyMapView.SpatialReference)
+ {
+ // Project the geometry to WGS84 (WGS84 is required by the KML standard).
+ Geometry projectedGeometry = geometry.Project(SpatialReferences.Wgs84);
+
+ // Create a KmlGeometry using the projected geometry.
+ kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround);
+ }
+ else
+ {
+ // Create a KmlGeometry using the user-drawn geometry.
+ kmlGeometry = new KmlGeometry(geometry, 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/UWP/ArcGIS.UWP.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs b/src/UWP/ArcGIS.UWP.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs
index a10e2af309..03e2de15fd 100644
--- a/src/UWP/ArcGIS.UWP.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs
+++ b/src/UWP/ArcGIS.UWP.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs
@@ -12,6 +12,7 @@
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.Tasks.NetworkAnalysis;
using Esri.ArcGISRuntime.UI;
+using Esri.ArcGISRuntime.UI.Editing;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -32,6 +33,9 @@ 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();
@@ -52,18 +56,12 @@ 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))
+ // Finish any barrier.
+ if (MyMapView.GeometryEditor.IsStarted && _geometryType == GeometryType.Polyline)
{
- // Set the event as handled.
- e.Handled = true;
-
- // Finish the sketch.
- MyMapView.SketchEditor.CompleteCommand.Execute(null);
- DrawBarrierButton.Content = "Draw barrier";
+ FinishBarrier();
}
};
}
@@ -72,9 +70,29 @@ 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);
+ // Let the user tap on the map view using the point geometry type.
+ _geometryType = GeometryType.Point;
+
+ // Start the geometry editor.
+ MyMapView.GeometryEditor.Start(_geometryType);
+ MyMapView.GeometryEditor.PropertyChanged += GeometryEditor_PropertyChanged;
+ }
+ catch (Exception ex)
+ {
+ // Report exceptions.
+ await new MessageDialog("Error drawing facility:\n" + ex.Message, "Sample error").ShowAsync();
+ }
+ }
+
+ private void GeometryEditor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(GeometryEditor.Geometry) && _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"))
@@ -91,15 +109,9 @@ private async void PlaceFacilityButton_Click(object sender, RoutedEventArgs e)
// Add the graphic to the graphics overlay.
MyMapView.GraphicsOverlays[0].Graphics.Add(facilityGraphic);
- }
- catch (TaskCanceledException)
- {
- // Ignore this exception.
- }
- catch (Exception ex)
- {
- // Report exceptions.
- await new MessageDialog("Error drawing facility:\n" + ex.Message, "Sample error").ShowAsync();
+
+ // Stop the geometry editor to clear the active geometry.
+ MyMapView.GeometryEditor.Stop();
}
}
@@ -108,8 +120,10 @@ 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,10 +132,25 @@ private async void DrawBarrierButton_Click(object sender, RoutedEventArgs e)
// Update the button label.
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);
+ // Let the user draw on the map view using the polyline geometry type.
+ _geometryType = GeometryType.Polyline;
+
+ // Start the geometry editor.
+ MyMapView.GeometryEditor.Start(_geometryType);
+ }
+ catch (Exception ex)
+ {
+ // Report exceptions.
+ await new MessageDialog("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,27 +162,18 @@ 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 MessageDialog("Error drawing barrier:\n" + ex.Message, "Sample error").ShowAsync();
+
+ // Update button text.
+ DrawBarrierButton.Content = "Draw barrier";
}
}
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);
- DrawBarrierButton.Content = "Draw barrier";
+ FinishBarrier();
}
// Use a local variable for the graphics overlay.
diff --git a/src/WPF/WPF.Viewer/Helpers/ArcGISLoginPrompt.cs b/src/WPF/WPF.Viewer/Helpers/ArcGISLoginPrompt.cs
index 3044e65170..55401bf810 100644
--- a/src/WPF/WPF.Viewer/Helpers/ArcGISLoginPrompt.cs
+++ b/src/WPF/WPF.Viewer/Helpers/ArcGISLoginPrompt.cs
@@ -87,29 +87,9 @@ public static async Task PromptCredentialAsync(CredentialRequestInfo
public static void SetChallengeHandler()
{
- // Define the server information for ArcGIS Online
- ServerInfo portalServerInfo = new ServerInfo(new Uri(ArcGISOnlineUrl))
- {
- TokenAuthenticationType = TokenAuthenticationType.OAuthAuthorizationCode,
- OAuthClientInfo = new OAuthClientInfo(AppClientId, new Uri(OAuthRedirectUrl))
- };
-
- // If a client secret has been configured, set the authentication type to OAuth client credentials.
- if (!string.IsNullOrEmpty(ClientSecret))
- {
- // If a client secret is specified then use the TokenAuthenticationType.OAuthClientCredentials type.
- portalServerInfo.TokenAuthenticationType = TokenAuthenticationType.OAuthClientCredentials;
- portalServerInfo.OAuthClientInfo.ClientSecret = ClientSecret;
- }
-
- // Register the ArcGIS Online server information with the AuthenticationManager
- AuthenticationManager.Current.RegisterServer(portalServerInfo);
-
- // Use the OAuthAuthorize class in this project to create a new web view to show the login UI
+ var userConfig = new OAuthUserConfiguration(new Uri(ArcGISOnlineUrl), AppClientId, new Uri(OAuthRedirectUrl));
+ AuthenticationManager.Current.OAuthUserConfigurations.Add(userConfig);
AuthenticationManager.Current.OAuthAuthorizeHandler = new OAuthAuthorize();
-
- // Create a new ChallengeHandler that uses a method in this class to challenge for credentials
- AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(PromptCredentialAsync);
}
#region OAuth handler
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml b/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
index 204ad7113f..37269da0b2 100644
--- a/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
+++ b/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml
@@ -29,9 +29,10 @@
+
-
+
-
+ Unchecked="UniformScaleCheckBox_CheckedChanged" />
-
-
-
- ()
{
{ "Vertex Tool", new VertexTool() },
+ { "Reticle Vertex Tool", new ReticleVertexTool() },
{ "Freehand Tool", new FreehandTool() },
{ "Arrow Shape Tool", ShapeTool.Create(ShapeToolType.Arrow) },
{ "Ellipse Shape Tool", ShapeTool.Create(ShapeToolType.Ellipse) },
@@ -199,11 +200,14 @@ private void ToolComboBox_SelectionChanged(object sender, SelectionChangedEventA
// Account for case when vertex tool is selected and geometry editor is started with a polyline or polygon geometry type.
// Ensure point and multipoint buttons are only enabled when the selected tool is a vertex tool.
- PointButton.IsEnabled = MultipointButton.IsEnabled = !_geometryEditor.IsStarted && _geometryEditor.Tool is VertexTool;
+ PointButton.IsEnabled = MultipointButton.IsEnabled = !_geometryEditor.IsStarted && (_geometryEditor.Tool is VertexTool || _geometryEditor.Tool is ReticleVertexTool);
+
+ // Uniform scale is not compatible with the reticle vertex tool.
+ UniformScaleBox.IsEnabled = !(_geometryEditor.Tool is ReticleVertexTool);
}
// Set the scale mode for every geometry editor tool.
- private void CheckBox_CheckedChanged(object sender, RoutedEventArgs e)
+ private void UniformScaleCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
// Determine the newly selected scale mode.
GeometryEditorScaleMode scaleMode =
@@ -364,7 +368,7 @@ private void ResetFromEditingSession()
_selectedGraphic = null;
// Point and multipoint sessions do not support the vertex tool.
- PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool;
+ PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool || _geometryEditor.Tool is ReticleVertexTool;
PolylineButton.IsEnabled = PolygonButton.IsEnabled = true;
ToolComboBox.IsEnabled = true;
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md b/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
index 85816c070d..77d186cc57 100644
--- a/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
+++ b/src/WPF/WPF.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
@@ -10,7 +10,9 @@ A field worker can mark features of interest on a map using an appropriate geome
## How to use the sample
-To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).
+To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map and then perform edits by tapping and dragging its elements. When using an appropriate tool to select a whole geometry, you can use the control handles to scale and rotate the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or one of the available `ShapeTool`s).
+
+When using the `ReticleVertexTool`, you can move the map position of the reticle by dragging and zooming the map. Insert a vertex under the reticle by tapping on the map. Move a vertex by tapping when the reticle is located over a vertex, drag the map to move the position of the reticle, then tap a second time to place the vertex.
Use the control panel to undo or redo changes made to the geometry, delete a selected element, save the geometry, stop the editing session and discard any edits, and remove all geometries from the map.
@@ -23,7 +25,7 @@ Use the control panel to undo or redo changes made to the geometry, delete a sel
* Access the `MapView.IdentifyGraphicsOverlayAsync(...)`.
* Find the desired graphic in the `results.FirstOrDefault()` list.
* Access the geometry associated with the `Graphic` using `Graphic.Geometry` - this will be used in the `GeometryEditor.Start(Geometry)` method.
-3. Create `VertexTool`, `FreehandTool`, or `ShapeTool` objects which define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
+3. Create `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or `ShapeTool` objects to define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
4. Edit a tool's InteractionConfiguration to set the GeometryEditorScaleMode to allow either uniform or stretch scale mode.
5. Check to see if undo and redo are possible during an editing session using `GeometryEditor.CanUndo` and `GeometryEditor.CanRedo`. If it's possible, use `GeometryEditor.Undo()` and `GeometryEditor.Redo()`.
6. Check whether the currently selected `GeometryEditorElement` can be deleted (`GeometryEditor.SelectedElement.CanDelete`). If the element can be deleted, delete using `GeometryEditor.DeleteSelectedElement()`.
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg
index d4b2530430..8e9af3029b 100644
Binary files a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg and b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg differ
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
index 7ae88154d5..70cd1a3868 100644
--- a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
+++ b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
@@ -52,7 +52,7 @@
@@ -61,10 +61,21 @@
Height="50"
ItemTemplate="{StaticResource SnapSettingTemplate}" />
+
+
+
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
index ae44f22496..7324fcddff 100644
--- a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
+++ b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
@@ -29,7 +29,7 @@ namespace ArcGIS.WPF.Samples.SnapGeometryEdits
category: "Geometry",
description: "Use the Geometry Editor to edit a geometry and align it to existing geometries on a map.",
instructions: "To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.",
- tags: new[] { "edit", "feature", "geometry editor", "layers", "map", "snapping" })]
+ tags: new[] { "edit", "feature", "geometry editor", "graphics", "layers", "map", "snapping" })]
public partial class SnapGeometryEdits
{
// Hold references for use in event handlers.
@@ -109,6 +109,9 @@ private void SetSnapSettings()
// Populate lists of snap source settings for point and polyline layers.
PointSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Point).ToList();
PolylineSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Polyline).ToList();
+
+ // Populate a list of snap source settings for graphics overlays.
+ GraphicsOverlaySnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingsVM => snapSourceSettingsVM.SnapSourceSettings.Source is GraphicsOverlay).ToList();
}
private void CreateNewGraphic()
@@ -264,6 +267,18 @@ private void DiscardButton_Click(object sender, RoutedEventArgs e)
#endregion
#region Geometry Tool Buttons Handlers
+ private void ReticleVertexToolCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
+ {
+ if (ReticleVertexToolCheckBox.IsChecked == true)
+ {
+ _geometryEditor.Tool = new ReticleVertexTool();
+ }
+ else
+ {
+ _geometryEditor.Tool = new VertexTool();
+ }
+ }
+
private void PointButton_Click(object sender, RoutedEventArgs e)
{
if (_geometryEditor.IsStarted)
@@ -325,10 +340,18 @@ public SnapSourceSettingsVM(SnapSourceSettings snapSourceSettings)
{
SnapSourceSettings = snapSourceSettings;
- if (snapSourceSettings.Source is FeatureLayer featureLayer && featureLayer.FeatureTable != null)
+ if (snapSourceSettings.Source is FeatureLayer featureLayer)
{
Name = featureLayer.Name;
- GeometryType = featureLayer.FeatureTable.GeometryType;
+
+ if (featureLayer.FeatureTable != null)
+ {
+ GeometryType = featureLayer.FeatureTable.GeometryType;
+ }
+ }
+ else if (snapSourceSettings.Source is GraphicsOverlay)
+ {
+ Name = "Editor graphics overlay";
}
IsEnabled = snapSourceSettings.IsEnabled;
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
index 343cb89c39..87c86309b8 100644
--- a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
+++ b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
@@ -12,11 +12,11 @@ A field worker can create new features by editing and snapping the vertices of a
To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.
-To configure snapping, press the snap settings button to enable or disable snapping and choose which layers to snap to.
+To configure snapping, press the snap settings button to enable or disable snapping and choose which snap sources to snap to.
-To interactively snap a vertex, ensure that snapping is enabled and move the mouse pointer or drag a vertex to nearby an existing feature. When the pointer is close to a feature, the edit position will be adjusted to coincide with (or snap to), edges and vertices of that feature. Click or release the touch pointer to place the vertex at the snapped location.
+To interactively snap a vertex to a feature or graphic, ensure that snapping is enabled for the relevant snap source and move the mouse pointer or drag a vertex to nearby an existing feature or graphic. When the pointer is close to that existing geoelement, the edit position will be adjusted to coincide with (or snap to), edges and vertices of its geometry. Click or release the touch pointer to place the vertex at the snapped location.
-To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features.
+To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features or graphics.
To undo changes made to the geometry, press the undo button.
@@ -39,6 +39,7 @@ To save your edits, press the save button.
* Geometry
* GeometryEditor
* GeometryEditorStyle
+* GraphicsOverlay
* MapView
* SnapSettings
* SnapSource
@@ -54,8 +55,8 @@ Snapping is used to maintain data integrity between different sources of data wh
To snap to polygon and polyline layers, the recommended approach is to set the `FeatureLayer`'s feature tiling mode to `FeatureTilingMode.EnabledWithFullResolutionWhenSupported` and use the default `ServiceFeatureTable` feature request mode `FeatureRequestMode.OnInteractionCache`. Local data sources, such as geodatabases, always provide full resolution geometries. Point and multipoint feature layers are also always full resolution.
-Snapping can be used during interactive edits that move existing vertices using the `VertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the magnifier to perform a vertex move allows users of touch devices to clearly see the visual cues for snapping.
+Snapping can be used during interactive edits that move existing vertices using the `VertexTool` or `ReticleVertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the `ReticleVertexTool` to add and move vertices allows users of touch screen devices to clearly see the visual cues for snapping.
## Tags
-edit, feature, geometry editor, layers, map, snapping
+edit, feature, geometry editor, graphics, layers, map, snapping
diff --git a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
index d955d5dfc4..a7ae1f3064 100644
--- a/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
+++ b/src/WPF/WPF.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
@@ -10,6 +10,7 @@
"edit",
"feature",
"geometry editor",
+ "graphics",
"layers",
"map",
"snapping"
@@ -23,6 +24,7 @@
"Geometry",
"GeometryEditor",
"GeometryEditorStyle",
+ "GraphicsOverlay",
"MapView",
"SnapSettings",
"SnapSource",
diff --git a/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.jpg b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.jpg
new file mode 100644
index 0000000000..748427cea0
Binary files /dev/null and b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.jpg differ
diff --git a/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml
new file mode 100644
index 0000000000..606cc26d96
--- /dev/null
+++ b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs
new file mode 100644
index 0000000000..0a95481ffd
--- /dev/null
+++ b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs
@@ -0,0 +1,90 @@
+// Copyright 2024 Esri.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
+// language governing permissions and limitations under the License.
+
+using Esri.ArcGISRuntime.Mapping;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace ArcGIS.WPF.Samples.CreateDynamicBasemapGallery
+{
+ [ArcGIS.Samples.Shared.Attributes.Sample(
+ name: "Create dynamic basemap gallery",
+ category: "Map",
+ description: "Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.",
+ instructions: "When launched, this sample displays a map containing a button that, when pressed, displays a gallery of all styles available in the basemap styles service. Selecting a style results in the drop-down menus at the base of the gallery becoming enabled or disabled. A disabled menu indicates that the customization cannot be applied to the selected style. Once a style and any desired customizations have been selected, pressing `Load` will update the basemap in the map view.",
+ tags: new[] { "basemap", "languages", "service", "style" })]
+ [ArcGIS.Samples.Shared.Attributes.OfflineData()]
+ public partial class CreateDynamicBasemapGallery
+ {
+ public CreateDynamicBasemapGallery()
+ {
+ InitializeComponent();
+ _ = Initialize();
+ }
+
+ private async Task Initialize()
+ {
+ // Create a new map with the ArcGIS Navigation basemap style.
+ MyMapView.Map = new Map(BasemapStyle.ArcGISNavigation);
+
+ // Create a new basemap styles service, pulling in the available styles and their information.
+ BasemapStylesServiceInfo service = await BasemapStylesServiceInfo.CreateAsync();
+
+ // Populate the basemap style gallery.
+ BasemapStyleGallery.ItemsSource = service.StylesInfo;
+
+ // Listen for basemap style selection events.
+ BasemapStyleGallery.SelectionChanged += BasemapStyleGallery_SelectionChanged;
+ }
+
+ private void BasemapStyleGallery_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ // Get the selected basemap style info.
+ var styleInfo = (BasemapStyleInfo)BasemapStyleGallery.SelectedItem;
+
+ // Set the pickers to the available options for the selected basemap.
+ StrategyPicker.ItemsSource = styleInfo.LanguageStrategies;
+ LanguagePicker.ItemsSource = styleInfo.Languages;
+ WorldviewPicker.ItemsSource = styleInfo.Worldviews;
+
+ // Disable any pickers that have no items.
+ LanguagePicker.IsEnabled = LanguagePicker.Items.Count > 0;
+ WorldviewPicker.IsEnabled = WorldviewPicker.Items.Count > 0;
+ StrategyPicker.IsEnabled = StrategyPicker.Items.Count > 0;
+ }
+
+ private void LoadButton_Click(object sender, RoutedEventArgs e)
+ {
+ // Return if no basemap style is selected.
+ if (BasemapStyleGallery.SelectedItem == null) return;
+
+ // Create a new basemap style parameters object.
+ var basemapStyleParameters = new BasemapStyleParameters();
+
+ // Set the language to the selected language.
+ if (LanguagePicker.SelectedItem != null)
+ basemapStyleParameters.SpecificLanguage = (LanguagePicker.SelectedItem as BasemapStyleLanguageInfo).CultureInfo;
+
+ // Set the worldview to the selected worldview.
+ if (WorldviewPicker.SelectedItem != null)
+ basemapStyleParameters.Worldview = (WorldviewPicker.SelectedItem as Worldview);
+
+ // Set the strategy to the selected strategy.
+ if (StrategyPicker.SelectedItem != null)
+ basemapStyleParameters.LanguageStrategy = (BasemapStyleLanguageStrategy)StrategyPicker.SelectedItem;
+
+ // Determine the basemap style of the currently selected basemap.
+ BasemapStyle selectedBasemapStyle = ((BasemapStyleInfo)BasemapStyleGallery.SelectedItem).Style;
+
+ // Update the map's basemap.
+ MyMapView.Map.Basemap = new Basemap(selectedBasemapStyle, basemapStyleParameters);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.md b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.md
new file mode 100644
index 0000000000..b84ad23ce0
--- /dev/null
+++ b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.md
@@ -0,0 +1,41 @@
+# Create dynamic basemap gallery
+
+Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.
+
+![CreateDynamicBasemapGallery](CreateDynamicBasemapGallery.jpg)
+
+## Use case
+
+Multi-use and/or international applications benefit from the ability to change a basemap's style or localize the basemap. For example, an application used for ecological surveys might include navigation functionality to guide an ecologist to a location and functionality for inputting data. When traveling, a user is likely to benefit from a map with a style that emphasizes the transport infrastructure (e.g. `ArcGIS Navigation`). However, during surveys a user is likely to benefit from a map with a style that highlights features in the terrain (e.g. `ArcGIS Terrain`). Implementing a basemap gallery with customization options in an application gives a user the freedom to select a basemap with a style and features (e.g. language of labels) suitable for the task they are undertaking. Making the basemap gallery dynamic ensures the latest customization options are automatically included.
+
+## How to use the sample
+
+When launched, this sample displays a map containing a button that, when pressed, displays a gallery of all styles available in the basemap styles service. Selecting a style results in the drop-down menus at the base of the gallery becoming enabled or disabled. A disabled menu indicates that the customization cannot be applied to the selected style. Once a style and any desired customizations have been selected, pressing `Load` will update the basemap in the map view.
+
+## How it works
+
+* Instantiate and load a `BasemapStylesServiceInfo` object.
+* Access the list of `BasemapStyleInfo` objects using `BasemapStylesServiceInfo.StylesInfo`. These `BasemapStyleInfo` objects contain up-to-date information about each of the styles supported by the Maps SDK, including:
+ * `StyleName`: The human-readable name of the style.
+ * `Style`: The `BasemapStyle` enumeration value representing this style in the Maps SDK.
+ * `Thumbnail`: An image that can be used to display a preview of the style.
+ * `Languages`: A list of `BasemapStyleLanguageInfo` objects, which provide information about each of the specific languages that can be used to customize labels on the style.
+ * `Worldviews`: A list of `Worldview` objects, which provide information about each representation of a disputed boundary that can be used to customize boundaries on the style.
+* The information contained in the list of `BasemapStyleInfo` objects can be used as the data model for a basemap gallery UI component.
+
+## Relevant API
+
+* BasemapStyleInfo
+* BasemapStyleLanguageInfo
+* BasemapStyleParameters
+* BasemapStylesService
+* BasemapStylesServiceInfo
+* Worldview
+
+## Additional information
+
+This sample demonstrates how to implement a basemap gallery using the Maps SDK. The styles and associated customization options used for the gallery are retrieved from the [basemap styles service](https://developers.arcgis.com/rest/basemap-styles/). A ready-made basemap gallery component is also available in the toolkit's provided with each SDK. To see how the ready-made basemap gallery toolkit component can be integrated into a Maps SDK application refer to the `Set Basemap` sample.
+
+## Tags
+
+basemap, languages, service, style
diff --git a/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json
new file mode 100644
index 0000000000..373e4e8411
--- /dev/null
+++ b/src/WPF/WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json
@@ -0,0 +1,32 @@
+{
+ "category": "Map",
+ "description": "Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.",
+ "formal_name": "CreateDynamicBasemapGallery",
+ "ignore": false,
+ "images": [
+ "CreateDynamicBasemapGallery.jpg"
+ ],
+ "keywords": [
+ "basemap",
+ "languages",
+ "service",
+ "style"
+ ],
+ "offline_data": [],
+ "redirect_from": [
+ "/net/latest/wpf/sample-code/create-dynamic-basemap-gallery.htm"
+ ],
+ "relevant_apis": [
+ "BasemapStyleInfo",
+ "BasemapStyleLanguageInfo",
+ "BasemapStyleParameters",
+ "BasemapStylesService",
+ "BasemapStylesServiceInfo",
+ "Worldview"
+ ],
+ "snippets": [
+ "CreateDynamicBasemapGallery.xaml.cs",
+ "CreateDynamicBasemapGallery.xaml"
+ ],
+ "title": "Create dynamic basemap gallery"
+}
\ No newline at end of file
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 eea5f07bd9..60696b77fb 100644
--- a/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs
+++ b/src/WPF/WPF.Viewer/Samples/NetworkAnalysis/FindServiceArea/FindServiceArea.xaml.cs
@@ -38,7 +38,7 @@ public FindServiceArea()
{
InitializeComponent();
- // Create the map, graphics overlay, and sketch editor.
+ // Create the map, graphics overlay, and geometry editor.
Initialize();
}
@@ -68,7 +68,7 @@ private void PlaceFacilityButton_Click(object sender, RoutedEventArgs e)
{
try
{
- // Let the user tap on the map view using the point sketch mode.
+ // Let the user tap on the map view using the point geometry type.
_geometryType = GeometryType.Point;
MyMapView.GeometryEditor.Start(_geometryType);
@@ -129,7 +129,7 @@ private void DrawBarrierButton_Click(object sender, RoutedEventArgs e)
// Update the button title.
DrawBarrierButton.Content = "Finish barrier";
- // Let the user draw on the map view using the polyline sketch mode.
+ // Let the user draw on the map view using the polyline geometry type.
_geometryType = GeometryType.Polyline;
MyMapView.GeometryEditor.Start(_geometryType);
diff --git a/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.md b/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.md
index 97cc39f3c3..17846232e1 100644
--- a/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.md
+++ b/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.md
@@ -14,17 +14,17 @@ When you run the sample, the app will load a web map which contains premium cont
## How it works
-1. Set the `AuthenticationManager`'s `ChallengeHandler`.
-2. Create a `ServerInfo` specifying the portal URL, client ID, and redirect URL.
-3. Register the server with the authentication manager.
+1. Create a `OAuthUserConfiguration` specifying the portal URL, app id, and redirect URL.
+2. Set the `AuthenticationManager`'s `OAuthUserConfigurations` with the new `OAuthUserConfiguration`.
+3. Set the `AuthenticationManager`'s `OAuthAuthorizeHandler` to an instance of a class which implements `IOAuthAuthorizationHandler`.
4. Load a map with premium content requiring authentication to automatically invoke the authentication handler.
## Relevant API
* AuthenticationManager
-* OAuthConfiguration
+* OAuthTokenCredential
+* OAuthUserConfiguration
* PortalItem
-* ServerInfo
## Additional information
@@ -35,4 +35,4 @@ For additional information on using Oauth in your app, see the [Mobile and Nativ
## Tags
-authentication, cloud, credential, OAuth, OAuth2, portal, security
\ No newline at end of file
+authentication, cloud, credential, OAuth, OAuth2, portal, security
diff --git a/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.metadata.json b/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.metadata.json
index f3f3454bb4..d4458a39eb 100644
--- a/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.metadata.json
+++ b/src/WPF/WPF.Viewer/Samples/Security/OAuth/readme.metadata.json
@@ -21,9 +21,9 @@
],
"relevant_apis": [
"AuthenticationManager",
- "OAuthConfiguration",
- "PortalItem",
- "ServerInfo"
+ "OAuthTokenCredential",
+ "OAuthUserConfiguration",
+ "PortalItem"
],
"snippets": [
"OAuth.xaml.cs",
diff --git a/src/WPF/readme.md b/src/WPF/readme.md
index d3f9035c55..91b1f60690 100644
--- a/src/WPF/readme.md
+++ b/src/WPF/readme.md
@@ -170,6 +170,7 @@
* [Change basemap](WPF.Viewer/Samples/Map/ChangeBasemap) - Change a map's basemap. A basemap is beneath all layers on a `Map` and is used to provide visual reference for the operational layers.
* [Configure basemap style parameters](WPF.Viewer/Samples/Map/ConfigureBasemapStyleParameters) - Apply basemap style parameters customization for a basemap, such as displaying all labels in a specific language or displaying every label in their corresponding local language.
* [Create and save map](WPF.Viewer/Samples/Map/AuthorMap) - Create and save a map as an ArcGIS `PortalItem` (i.e. web map).
+* [Create dynamic basemap gallery](WPF.Viewer/Samples/Map/CreateDynamicBasemapGallery) - Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.
* [Display map](WPF.Viewer/Samples/Map/DisplayMap) - Display a map with an imagery basemap.
* [Display overview map](WPF.Viewer/Samples/Map/DisplayOverviewMap) - Include an overview or inset map as an additional map view to show the wider context of the primary view.
* [Download preplanned map area](WPF.Viewer/Samples/Map/DownloadPreplannedMap) - Take a map offline using a preplanned map area.
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Helpers/ArcGISLoginPrompt.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Helpers/ArcGISLoginPrompt.cs
index b82d3dbb98..01342c6314 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Helpers/ArcGISLoginPrompt.cs
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Helpers/ArcGISLoginPrompt.cs
@@ -88,28 +88,8 @@ public static async Task PromptCredentialAsync(CredentialRequestInfo
public static void SetChallengeHandler(UserControl sample)
{
- // Define the server information for ArcGIS Online
- ServerInfo portalServerInfo = new ServerInfo(new Uri(ArcGISOnlineUrl))
- {
- TokenAuthenticationType = TokenAuthenticationType.OAuthAuthorizationCode,
- OAuthClientInfo = new OAuthClientInfo(AppClientId, new Uri(OAuthRedirectUrl))
- };
-
- // If a client secret has been configured, set the authentication type to OAuth client credentials.
- if (!string.IsNullOrEmpty(ClientSecret))
- {
- // If a client secret is specified then use the TokenAuthenticationType.OAuthClientCredentials type.
- portalServerInfo.TokenAuthenticationType = TokenAuthenticationType.OAuthClientCredentials;
- portalServerInfo.OAuthClientInfo.ClientSecret = ClientSecret;
- }
-
- // Register the ArcGIS Online server information with the AuthenticationManager
- AuthenticationManager.Current.RegisterServer(portalServerInfo);
-
- // Create a new ChallengeHandler that uses a method in this class to challenge for credentials
- AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(PromptCredentialAsync);
-
- // Use the OAuthAuthorize class in this project to create a new web view to show the login UI
+ var userConfig = new OAuthUserConfiguration(new Uri(ArcGISOnlineUrl), AppClientId, new Uri(OAuthRedirectUrl));
+ AuthenticationManager.Current.OAuthUserConfigurations.Add(userConfig);
AuthenticationManager.Current.OAuthAuthorizeHandler = new OAuthAuthorize(sample);
}
}
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
index 0fb79592ac..e8f4e2194e 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/CreateAndEditGeometries.xaml.cs
@@ -29,7 +29,7 @@ namespace ArcGIS.WinUI.Samples.CreateAndEditGeometries
name: "Create and edit geometries",
category: "Geometry",
description: "Use the Geometry Editor to create new point, multipoint, polyline, or polygon geometries or to edit existing geometries by interacting with a map view.",
- instructions: "To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).",
+ instructions: "To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map and then perform edits by tapping and dragging its elements. When using an appropriate tool to select a whole geometry, you can use the control handles to scale and rotate the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or one of the available `ShapeTool`s).",
tags: new[] { "draw", "edit", "freehand", "geometry editor", "sketch", "vertex" })]
public partial class CreateAndEditGeometries
{
@@ -110,6 +110,7 @@ private void Initialize()
ToolComboBox.ItemsSource = _toolDictionary = new Dictionary()
{
{ "Vertex Tool", new VertexTool() },
+ { "Reticle Vertex Tool", new ReticleVertexTool() },
{ "Freehand Tool", new FreehandTool() },
{ "Arrow Shape Tool", ShapeTool.Create(ShapeToolType.Arrow) },
{ "Ellipse Shape Tool", ShapeTool.Create(ShapeToolType.Ellipse) },
@@ -200,6 +201,9 @@ private void ToolComboBox_SelectionChanged(object sender, SelectionChangedEventA
// Account for case when vertex tool is selected and geometry editor is started with a polyline or polygon geometry type.
// Ensure point and multipoint buttons are only enabled when the selected tool is a vertex tool.
PointButton.IsEnabled = MultipointButton.IsEnabled = !_geometryEditor.IsStarted && _geometryEditor.Tool is VertexTool;
+
+ // Uniform scale is not compatible with the reticle vertex tool.
+ UniformScaleCheckBox.IsEnabled = !(_geometryEditor.Tool is ReticleVertexTool);
}
// Set the scale mode for every geometry editor tool.
@@ -365,7 +369,7 @@ private void ResetFromEditingSession()
_selectedGraphic = null;
// Point and multipoint sessions do not support the vertex tool.
- PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool;
+ PointButton.IsEnabled = MultipointButton.IsEnabled = _geometryEditor.Tool is VertexTool || _geometryEditor.Tool is ReticleVertexTool;
PolylineButton.IsEnabled = PolygonButton.IsEnabled = true;
ToolComboBox.IsEnabled = true;
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
index 85816c070d..77d186cc57 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/CreateAndEditGeometries/readme.md
@@ -10,7 +10,9 @@ A field worker can mark features of interest on a map using an appropriate geome
## How to use the sample
-To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging elements of the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool` or `FreehandTool`).
+To create a new geometry, press the button appropriate for the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry. To edit an existing geometry, tap the geometry to be edited in the map and then perform edits by tapping and dragging its elements. When using an appropriate tool to select a whole geometry, you can use the control handles to scale and rotate the geometry. If creating or editing polyline or polygon geometries, choose the desired creation/editing tool (i.e. `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or one of the available `ShapeTool`s).
+
+When using the `ReticleVertexTool`, you can move the map position of the reticle by dragging and zooming the map. Insert a vertex under the reticle by tapping on the map. Move a vertex by tapping when the reticle is located over a vertex, drag the map to move the position of the reticle, then tap a second time to place the vertex.
Use the control panel to undo or redo changes made to the geometry, delete a selected element, save the geometry, stop the editing session and discard any edits, and remove all geometries from the map.
@@ -23,7 +25,7 @@ Use the control panel to undo or redo changes made to the geometry, delete a sel
* Access the `MapView.IdentifyGraphicsOverlayAsync(...)`.
* Find the desired graphic in the `results.FirstOrDefault()` list.
* Access the geometry associated with the `Graphic` using `Graphic.Geometry` - this will be used in the `GeometryEditor.Start(Geometry)` method.
-3. Create `VertexTool`, `FreehandTool`, or `ShapeTool` objects which define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
+3. Create `VertexTool`, `ReticleVertexTool`, `FreehandTool`, or `ShapeTool` objects to define how the user interacts with the view to create or edit geometries, setting `GeometryEditor.Tool`.
4. Edit a tool's InteractionConfiguration to set the GeometryEditorScaleMode to allow either uniform or stretch scale mode.
5. Check to see if undo and redo are possible during an editing session using `GeometryEditor.CanUndo` and `GeometryEditor.CanRedo`. If it's possible, use `GeometryEditor.Undo()` and `GeometryEditor.Redo()`.
6. Check whether the currently selected `GeometryEditorElement` can be deleted (`GeometryEditor.SelectedElement.CanDelete`). If the element can be deleted, delete using `GeometryEditor.DeleteSelectedElement()`.
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg
index 115be69a7e..e048290022 100644
Binary files a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg and b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.jpg differ
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
index 011c7ae1b8..86dd7fd400 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml
@@ -45,108 +45,129 @@
Background="White"
CornerRadius="5"
Visibility="Collapsed">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
index 72d5e0cb3d..b4a09b727c 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/SnapGeometryEdits.xaml.cs
@@ -30,7 +30,7 @@ namespace ArcGIS.WinUI.Samples.SnapGeometryEdits
category: "Geometry",
description: "Use the Geometry Editor to edit a geometry and align it to existing geometries on a map.",
instructions: "To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.",
- tags: new[] { "edit", "feature", "geometry editor", "layers", "map", "snapping" })]
+ tags: new[] { "edit", "feature", "geometry editor", "graphics", "layers", "map", "snapping" })]
public partial class SnapGeometryEdits
{
// Hold references for use in event handlers.
@@ -111,6 +111,9 @@ private void SetSnapSettings()
// Populate lists of snap source settings for point and polyline layers.
PointSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Point).ToList();
PolylineSnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingVM => snapSourceSettingVM.GeometryType == GeometryType.Polyline).ToList();
+
+ // Populate a list of snap source settings for graphics overlays.
+ GraphicsOverlaySnapSettingsList.ItemsSource = snapSourceSettingsVMs.Where(snapSourceSettingsVMs => snapSourceSettingsVMs.SnapSourceSettings.Source is GraphicsOverlay).ToList();
}
private void CreateNewGraphic()
@@ -266,6 +269,18 @@ private void DiscardButton_Click(object sender, RoutedEventArgs e)
#endregion
#region Geometry Tool Buttons Handlers
+ private void ReticleVertexToolCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
+ {
+ if (ReticleVertexToolCheckBox.IsChecked == true)
+ {
+ _geometryEditor.Tool = new ReticleVertexTool();
+ }
+ else
+ {
+ _geometryEditor.Tool = new VertexTool();
+ }
+ }
+
private void PointButton_Click(object sender, RoutedEventArgs e)
{
if (_geometryEditor.IsStarted)
@@ -327,10 +342,18 @@ public SnapSourceSettingsVM(SnapSourceSettings snapSourceSettings)
{
SnapSourceSettings = snapSourceSettings;
- if (snapSourceSettings.Source is FeatureLayer featureLayer && featureLayer.FeatureTable != null)
+ if (snapSourceSettings.Source is FeatureLayer featureLayer)
{
Name = featureLayer.Name;
- GeometryType = featureLayer.FeatureTable.GeometryType;
+
+ if (featureLayer.FeatureTable != null)
+ {
+ GeometryType = featureLayer.FeatureTable.GeometryType;
+ }
+ }
+ else if (snapSourceSettings.Source is GraphicsOverlay graphicsOverlay)
+ {
+ Name = "Editor graphics overlay";
}
IsEnabled = snapSourceSettings.IsEnabled;
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
index 343cb89c39..87c86309b8 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.md
@@ -12,11 +12,11 @@ A field worker can create new features by editing and snapping the vertices of a
To create a geometry, press the create button to choose the geometry type you want to create (i.e. points, multipoints, polyline, or polygon) and interactively tap and drag on the map view to create the geometry.
-To configure snapping, press the snap settings button to enable or disable snapping and choose which layers to snap to.
+To configure snapping, press the snap settings button to enable or disable snapping and choose which snap sources to snap to.
-To interactively snap a vertex, ensure that snapping is enabled and move the mouse pointer or drag a vertex to nearby an existing feature. When the pointer is close to a feature, the edit position will be adjusted to coincide with (or snap to), edges and vertices of that feature. Click or release the touch pointer to place the vertex at the snapped location.
+To interactively snap a vertex to a feature or graphic, ensure that snapping is enabled for the relevant snap source and move the mouse pointer or drag a vertex to nearby an existing feature or graphic. When the pointer is close to that existing geoelement, the edit position will be adjusted to coincide with (or snap to), edges and vertices of its geometry. Click or release the touch pointer to place the vertex at the snapped location.
-To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features.
+To edit a geometry, tap the geometry to be edited in the map to select it and then edit the geometry by tapping and dragging its vertices and snapping them to nearby features or graphics.
To undo changes made to the geometry, press the undo button.
@@ -39,6 +39,7 @@ To save your edits, press the save button.
* Geometry
* GeometryEditor
* GeometryEditorStyle
+* GraphicsOverlay
* MapView
* SnapSettings
* SnapSource
@@ -54,8 +55,8 @@ Snapping is used to maintain data integrity between different sources of data wh
To snap to polygon and polyline layers, the recommended approach is to set the `FeatureLayer`'s feature tiling mode to `FeatureTilingMode.EnabledWithFullResolutionWhenSupported` and use the default `ServiceFeatureTable` feature request mode `FeatureRequestMode.OnInteractionCache`. Local data sources, such as geodatabases, always provide full resolution geometries. Point and multipoint feature layers are also always full resolution.
-Snapping can be used during interactive edits that move existing vertices using the `VertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the magnifier to perform a vertex move allows users of touch devices to clearly see the visual cues for snapping.
+Snapping can be used during interactive edits that move existing vertices using the `VertexTool` or `ReticleVertexTool`. It is also supported for adding new vertices for input devices with a hover event (such as a mouse move without a mouse button press). Using the `ReticleVertexTool` to add and move vertices allows users of touch screen devices to clearly see the visual cues for snapping.
## Tags
-edit, feature, geometry editor, layers, map, snapping
+edit, feature, geometry editor, graphics, layers, map, snapping
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
index 64dc33a78c..608afeb0d0 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Geometry/SnapGeometryEdits/readme.metadata.json
@@ -10,6 +10,7 @@
"edit",
"feature",
"geometry editor",
+ "graphics",
"layers",
"map",
"snapping"
@@ -23,6 +24,7 @@
"Geometry",
"GeometryEditor",
"GeometryEditorStyle",
+ "GraphicsOverlay",
"MapView",
"SnapSettings",
"SnapSource",
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.jpg b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.jpg
new file mode 100644
index 0000000000..d6b6e62acd
Binary files /dev/null and b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.jpg differ
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml
new file mode 100644
index 0000000000..4806741bcf
--- /dev/null
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs
new file mode 100644
index 0000000000..f00b4b9d27
--- /dev/null
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/CreateDynamicBasemapGallery.xaml.cs
@@ -0,0 +1,90 @@
+// Copyright 2024 Esri.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
+// language governing permissions and limitations under the License.
+
+using Esri.ArcGISRuntime.Mapping;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using System.Threading.Tasks;
+
+namespace ArcGIS.WinUI.Samples.CreateDynamicBasemapGallery
+{
+ [ArcGIS.Samples.Shared.Attributes.Sample(
+ name: "Create dynamic basemap gallery",
+ category: "Map",
+ description: "Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.",
+ instructions: "When launched, this sample displays a map containing a button that, when pressed, displays a gallery of all styles available in the basemap styles service. Selecting a style results in the drop-down menus at the base of the gallery becoming enabled or disabled. A disabled menu indicates that the customization cannot be applied to the selected style. Once a style and any desired customizations have been selected, pressing `Load` will update the basemap in the map view.",
+ tags: new[] { "basemap", "languages", "service", "style" })]
+ [ArcGIS.Samples.Shared.Attributes.OfflineData()]
+ public partial class CreateDynamicBasemapGallery
+ {
+ public CreateDynamicBasemapGallery()
+ {
+ InitializeComponent();
+ _ = Initialize();
+ }
+
+ private async Task Initialize()
+ {
+ // Create a new map with the ArcGIS Navigation basemap style.
+ MyMapView.Map = new Map(BasemapStyle.ArcGISNavigation);
+
+ // Create a new basemap styles service, pulling in the available styles and their information.
+ BasemapStylesServiceInfo service = await BasemapStylesServiceInfo.CreateAsync();
+
+ // Populate the basemap style gallery.
+ BasemapStyleGallery.ItemsSource = service.StylesInfo;
+
+ // Listen for basemap style selection events.
+ BasemapStyleGallery.SelectionChanged += BasemapStyleGallery_SelectionChanged;
+ }
+
+ private void BasemapStyleGallery_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ // Get the selected basemap style info.
+ var styleInfo = (BasemapStyleInfo)BasemapStyleGallery.SelectedItem;
+
+ // Set the pickers to the available options for the selected basemap.
+ StrategyPicker.ItemsSource = styleInfo.LanguageStrategies;
+ LanguagePicker.ItemsSource = styleInfo.Languages;
+ WorldviewPicker.ItemsSource = styleInfo.Worldviews;
+
+ // Disable any pickers that have no items.
+ LanguagePicker.IsEnabled = LanguagePicker.Items.Count > 0;
+ WorldviewPicker.IsEnabled = WorldviewPicker.Items.Count > 0;
+ StrategyPicker.IsEnabled = StrategyPicker.Items.Count > 0;
+ }
+
+ private void LoadButton_Click(object sender, RoutedEventArgs e)
+ {
+ // Return if no basemap style is selected.
+ if (BasemapStyleGallery.SelectedItem == null) return;
+
+ // Create a new basemap style parameters object.
+ var basemapStyleParameters = new BasemapStyleParameters();
+
+ // Set the language to the selected language.
+ if (LanguagePicker.SelectedItem != null)
+ basemapStyleParameters.SpecificLanguage = (LanguagePicker.SelectedItem as BasemapStyleLanguageInfo).CultureInfo;
+
+ // Set the worldview to the selected worldview.
+ if (WorldviewPicker.SelectedItem != null)
+ basemapStyleParameters.Worldview = (WorldviewPicker.SelectedItem as Worldview);
+
+ // Set the strategy to the selected strategy.
+ if (StrategyPicker.SelectedItem != null)
+ basemapStyleParameters.LanguageStrategy = (BasemapStyleLanguageStrategy)StrategyPicker.SelectedItem;
+
+ // Determine the basemap style of the currently selected basemap.
+ BasemapStyle selectedBasemapStyle = ((BasemapStyleInfo)BasemapStyleGallery.SelectedItem).Style;
+
+ // Update the map's basemap.
+ MyMapView.Map.Basemap = new Basemap(selectedBasemapStyle, basemapStyleParameters);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.md
new file mode 100644
index 0000000000..b84ad23ce0
--- /dev/null
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.md
@@ -0,0 +1,41 @@
+# Create dynamic basemap gallery
+
+Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.
+
+![CreateDynamicBasemapGallery](CreateDynamicBasemapGallery.jpg)
+
+## Use case
+
+Multi-use and/or international applications benefit from the ability to change a basemap's style or localize the basemap. For example, an application used for ecological surveys might include navigation functionality to guide an ecologist to a location and functionality for inputting data. When traveling, a user is likely to benefit from a map with a style that emphasizes the transport infrastructure (e.g. `ArcGIS Navigation`). However, during surveys a user is likely to benefit from a map with a style that highlights features in the terrain (e.g. `ArcGIS Terrain`). Implementing a basemap gallery with customization options in an application gives a user the freedom to select a basemap with a style and features (e.g. language of labels) suitable for the task they are undertaking. Making the basemap gallery dynamic ensures the latest customization options are automatically included.
+
+## How to use the sample
+
+When launched, this sample displays a map containing a button that, when pressed, displays a gallery of all styles available in the basemap styles service. Selecting a style results in the drop-down menus at the base of the gallery becoming enabled or disabled. A disabled menu indicates that the customization cannot be applied to the selected style. Once a style and any desired customizations have been selected, pressing `Load` will update the basemap in the map view.
+
+## How it works
+
+* Instantiate and load a `BasemapStylesServiceInfo` object.
+* Access the list of `BasemapStyleInfo` objects using `BasemapStylesServiceInfo.StylesInfo`. These `BasemapStyleInfo` objects contain up-to-date information about each of the styles supported by the Maps SDK, including:
+ * `StyleName`: The human-readable name of the style.
+ * `Style`: The `BasemapStyle` enumeration value representing this style in the Maps SDK.
+ * `Thumbnail`: An image that can be used to display a preview of the style.
+ * `Languages`: A list of `BasemapStyleLanguageInfo` objects, which provide information about each of the specific languages that can be used to customize labels on the style.
+ * `Worldviews`: A list of `Worldview` objects, which provide information about each representation of a disputed boundary that can be used to customize boundaries on the style.
+* The information contained in the list of `BasemapStyleInfo` objects can be used as the data model for a basemap gallery UI component.
+
+## Relevant API
+
+* BasemapStyleInfo
+* BasemapStyleLanguageInfo
+* BasemapStyleParameters
+* BasemapStylesService
+* BasemapStylesServiceInfo
+* Worldview
+
+## Additional information
+
+This sample demonstrates how to implement a basemap gallery using the Maps SDK. The styles and associated customization options used for the gallery are retrieved from the [basemap styles service](https://developers.arcgis.com/rest/basemap-styles/). A ready-made basemap gallery component is also available in the toolkit's provided with each SDK. To see how the ready-made basemap gallery toolkit component can be integrated into a Maps SDK application refer to the `Set Basemap` sample.
+
+## Tags
+
+basemap, languages, service, style
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json
new file mode 100644
index 0000000000..7bd306d323
--- /dev/null
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery/readme.metadata.json
@@ -0,0 +1,32 @@
+{
+ "category": "Map",
+ "description": "Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.",
+ "formal_name": "CreateDynamicBasemapGallery",
+ "ignore": false,
+ "images": [
+ "CreateDynamicBasemapGallery.jpg"
+ ],
+ "keywords": [
+ "basemap",
+ "languages",
+ "service",
+ "style"
+ ],
+ "offline_data": [],
+ "redirect_from": [
+ "/net/latest/winui/sample-code/create-dynamic-basemap-gallery.htm"
+ ],
+ "relevant_apis": [
+ "BasemapStyleInfo",
+ "BasemapStyleLanguageInfo",
+ "BasemapStyleParameters",
+ "BasemapStylesService",
+ "BasemapStylesServiceInfo",
+ "Worldview"
+ ],
+ "snippets": [
+ "CreateDynamicBasemapGallery.xaml.cs",
+ "CreateDynamicBasemapGallery.xaml"
+ ],
+ "title": "Create dynamic basemap gallery"
+}
\ No newline at end of file
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 844a2936b4..a2da53b413 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
@@ -38,7 +38,7 @@ public FindServiceArea()
{
InitializeComponent();
- // Create the map, graphics overlay, and sketch editor.
+ // Create the map, graphics overlay, and geometry editor.
Initialize();
}
@@ -68,7 +68,7 @@ private async void PlaceFacilityButton_Click(object sender, RoutedEventArgs e)
{
try
{
- // Let the user tap on the map view using the point sketch mode.
+ // Let the user tap on the map view using the point geometry type.
_geometryType = GeometryType.Point;
// Start the geometry editor.
@@ -130,7 +130,7 @@ private async void DrawBarrierButton_Click(object sender, RoutedEventArgs e)
// Update the button label.
DrawBarrierButton.Content = "Finish drawing";
- // Let the user draw on the map view using the polyline sketch mode.
+ // Let the user draw on the map view using the polyline geometry type.
_geometryType = GeometryType.Polyline;
// Start the geometry editor.
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.md b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.md
index 97cc39f3c3..17846232e1 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.md
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.md
@@ -14,17 +14,17 @@ When you run the sample, the app will load a web map which contains premium cont
## How it works
-1. Set the `AuthenticationManager`'s `ChallengeHandler`.
-2. Create a `ServerInfo` specifying the portal URL, client ID, and redirect URL.
-3. Register the server with the authentication manager.
+1. Create a `OAuthUserConfiguration` specifying the portal URL, app id, and redirect URL.
+2. Set the `AuthenticationManager`'s `OAuthUserConfigurations` with the new `OAuthUserConfiguration`.
+3. Set the `AuthenticationManager`'s `OAuthAuthorizeHandler` to an instance of a class which implements `IOAuthAuthorizationHandler`.
4. Load a map with premium content requiring authentication to automatically invoke the authentication handler.
## Relevant API
* AuthenticationManager
-* OAuthConfiguration
+* OAuthTokenCredential
+* OAuthUserConfiguration
* PortalItem
-* ServerInfo
## Additional information
@@ -35,4 +35,4 @@ For additional information on using Oauth in your app, see the [Mobile and Nativ
## Tags
-authentication, cloud, credential, OAuth, OAuth2, portal, security
\ No newline at end of file
+authentication, cloud, credential, OAuth, OAuth2, portal, security
diff --git a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.metadata.json b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.metadata.json
index 73f1dc324e..ec05dde35a 100644
--- a/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.metadata.json
+++ b/src/WinUI/ArcGIS.WinUI.Viewer/Samples/Security/OAuth/readme.metadata.json
@@ -21,9 +21,9 @@
],
"relevant_apis": [
"AuthenticationManager",
- "OAuthConfiguration",
- "PortalItem",
- "ServerInfo"
+ "OAuthTokenCredential",
+ "OAuthUserConfiguration",
+ "PortalItem"
],
"snippets": [
"OAuth.xaml.cs",
diff --git a/src/WinUI/readme.md b/src/WinUI/readme.md
index e2fac8bba5..5303938983 100644
--- a/src/WinUI/readme.md
+++ b/src/WinUI/readme.md
@@ -167,6 +167,7 @@
* [Change basemap](ArcGIS.WinUI.Viewer/Samples/Map/ChangeBasemap) - Change a map's basemap. A basemap is beneath all layers on a `Map` and is used to provide visual reference for the operational layers.
* [Configure basemap style parameters](ArcGIS.WinUI.Viewer/Samples/Map/ConfigureBasemapStyleParameters) - Apply basemap style parameters customization for a basemap, such as displaying all labels in a specific language or displaying every label in their corresponding local language.
* [Create and save map](ArcGIS.WinUI.Viewer/Samples/Map/AuthorMap) - Create and save a map as an ArcGIS `PortalItem` (i.e. web map).
+* [Create dynamic basemap gallery](ArcGIS.WinUI.Viewer/Samples/Map/CreateDynamicBasemapGallery) - Implement a basemap gallery that automatically retrieves the latest customization options from the basemap styles service.
* [Display map](ArcGIS.WinUI.Viewer/Samples/Map/DisplayMap) - Display a map with an imagery basemap.
* [Download preplanned map area](ArcGIS.WinUI.Viewer/Samples/Map/DownloadPreplannedMap) - Take a map offline using a preplanned map area.
* [Generate offline map](ArcGIS.WinUI.Viewer/Samples/Map/GenerateOfflineMap) - Take a web map offline.
diff --git a/tools/GenerateApps.msbuild b/tools/GenerateApps.msbuild
index c747e34d84..f05d1e816a 100644
--- a/tools/GenerateApps.msbuild
+++ b/tools/GenerateApps.msbuild
@@ -5,7 +5,7 @@
<_NetWindowsTarget>net8.0-windows10.0.19041.0
<_NetAndroidTarget>net8.0-android
Release
- 200.4.0
+ 200.5.00$(RELEASE_VERSION)
diff --git a/tools/cibuild.cmd b/tools/cibuild.cmd
index 5f15f780a7..02a23f4db5 100644
--- a/tools/cibuild.cmd
+++ b/tools/cibuild.cmd
@@ -12,7 +12,7 @@ IF "%VSINSTALLDIR%"=="" (
)
IF "%RELEASE_VERSION%" == "" (
- SET RELEASE_VERSION=200.3.0
+ SET RELEASE_VERSION=200.5.0
)
REM Configure NuGet
@@ -38,6 +38,9 @@ IF "%ArcGISLicenseKey%" NEQ "" (
IF "%ArcGISUtilityNetworkLicenseKey%" NEQ "" (
ECHO ArcGISUtilityNetworkLicenseKey = "%ArcGISUtilityNetworkLicenseKey%"; >>%licenseFile%
)
+ IF "%ArcGISAdvancedEditingUserTypeLicenseKey%" NEQ "" (
+ ECHO ArcGISAdvancedEditingUserTypeLicenseKey = "%ArcGISAdvancedEditingUserTypeLicenseKey%"; >>%licenseFile%
+ )
ECHO ^}^}^} >>%licenseFile%
)