Add SketchWidget as Custom Editor Pro sample#21
Conversation
Demonstrates driving the SketchWidget programmatically from C# while presenting a fully custom UI: a Move button arms an OnMapClick handler that hit-tests a target FeatureLayer, stages the picked Graphic into a companion GraphicsLayer, and hands it to SketchWidget.Update with a SketchToolUpdateOptions configured for SketchTool.Move. A Save button calls Complete() to finalize the edit (forwarded through FeatureLayer.ApplyEdits); a Cancel button (or the Esc key) calls Cancel() and skips ApplyEdits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new GeoBlazor Pro sample page (/sketch-as-editor) that uses SketchWidget.Update(SketchTool.Move) to implement a custom “Move / Save / Cancel” editing workflow with the built-in Sketch toolbar kept out of view, plus navigation and styling updates to surface the sample in the Pro menu.
Changes:
- Introduces the new
SketchAsEditorsample page and its scoped CSS for a custom editor toolbar/status UI. - Adds a Pro navigation entry pointing to the new sample, using a new
sketchEditor.svgicon. - Updates Pro shared
_Imports.razorto includedymaptic.GeoBlazor.Pro.Options(needed forSketchToolUpdateOptions).
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/ProNavMenu.cs | Adds a new nav link for the “PRO: Sketch as Editor” sample using the new SVG icon. |
| samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SketchAsEditor.razor | New sample page implementing the custom Sketch-driven move editor workflow and page metadata/description. |
| samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SketchAsEditor.razor.css | Scoped styling for the custom editor toolbar and status pill. |
| samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/_Imports.razor | Imports dymaptic.GeoBlazor.Pro.Options so the sample can reference SketchToolUpdateOptions. |
| samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/sketchEditor.svg | Adds the SVG icon used by the new Pro nav entry (served from Core Sample Shared static assets). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private async Task OnMapClick(ClickEvent evt) | ||
| { | ||
| if (!_moveArmed || _mapView is null || _featureLayer is null || _sketchWidget is null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // One-shot: disarm immediately so a missed click doesn't stay sticky. | ||
| _moveArmed = false; | ||
|
|
||
| HitTestOptions options = new() | ||
| { | ||
| IncludeByGeoBlazorId = [_featureLayer.Id] | ||
| }; | ||
| HitTestResult hit = await _mapView.HitTest(evt, options); | ||
| Graphic? graphic = hit.Results.OfType<GraphicHit>().FirstOrDefault()?.Graphic; | ||
|
|
||
| if (graphic is null) | ||
| { | ||
| _statusMessage = "No feature at that point."; | ||
| return; | ||
| } | ||
|
|
||
| // Stage the picked graphic into the Sketch's own GraphicsLayer so the widget can operate on it. | ||
| await _sketchLayer!.Add(graphic); | ||
| await _sketchWidget.Update([graphic], _updateOptions); | ||
| _editing = true; |
There was a problem hiding this comment.
Fixed in commit 30fe1e4 — added _sketchLayer is null to the early-return guard in OnMapClick and removed the null-forgiving ! operator from the subsequent _sketchLayer.Add(graphic) call.
| _editing = false; | ||
| Graphic? moved = evt.Graphics?.FirstOrDefault(); | ||
|
|
||
| // Cancel() fires Complete with Aborted=true; skip ApplyEdits but still clean up the staging graphic. | ||
| if (evt.Aborted == true) | ||
| { | ||
| if (moved is not null) | ||
| { | ||
| await _sketchLayer!.Remove(moved); | ||
| } |
| "SketchUpdateEvent is forwarded to FeatureLayer.ApplyEdits to persist the new geometry on the feature " + | ||
| "service, then the staging graphic is removed and the feature layer is refreshed so it redraws at the " + | ||
| "updated location. A Cancel button (and the Esc key) route through OnKeyDown to SketchWidget.Cancel(), " + | ||
| "which fires a Complete event with Aborted=true so ApplyEdits is skipped. The pattern is useful any time " + | ||
| "you need SketchViewModel's interactive move semantics inside a custom workflow with your own editor UI."; |
There was a problem hiding this comment.
@copilot fix this, but add text that points out it would also work with a hosted FeatureService.
There was a problem hiding this comment.
Done in commit 5cd3f62. The description now says ApplyEdits targets the client-side in-memory source layer, and adds a sentence noting that the same call works equally well against a hosted FeatureService — just replace Source with a Url.
Agent-Logs-Url: https://github.com/dymaptic/GeoBlazor-Samples/sessions/8c2e5f83-5053-4908-bab5-cae978cfdaaf Co-authored-by: TimPurdum <17970404+TimPurdum@users.noreply.github.com>
… works too Agent-Logs-Url: https://github.com/dymaptic/GeoBlazor-Samples/sessions/4039a7e9-6520-4247-a188-2823964dc4da Co-authored-by: TimPurdum <17970404+TimPurdum@users.noreply.github.com>
Summary
/sketch-as-editor) demonstrating how to drive theSketchWidgetprogrammatically from C# while presenting a fully custom UI (Move/Save/Cancel buttons) and keeping the widget's built-in toolbar hidden.OnMapClickhandler that hit-tests a targetFeatureLayer, stages the pickedGraphicinto a companionGraphicsLayer, and hands it toSketchWidget.Updateconfigured forSketchTool.Move. Save callsComplete()→FeatureLayer.ApplyEdits; Cancel/Esc callsCancel()and skipsApplyEditsvia theAbortedflag onSketchUpdateEvent.sketchEditor.svgicon, plus a small page-scoped stylesheet for the editor toolbar.Test plan
samples/pro/dymaptic.GeoBlazor.Pro.Sample.Sharedcleanly.dymaptic.GeoBlazor.Pro.Sample.Wasmor.WebApp) and navigate to PRO: Sketch as Editor.ApplyEditsand the layer refreshes with the new geometry.🤖 Generated with Claude Code