protected override Task HandleMouseDownAsync(MapViewMouseButtonEventArgs e) { //Select a line feature and place the initial graphic. Clear out any //previously placed graphic return(QueuedTask.Run(() => { var mapPoint = this.ActiveMapView.ClientToMap(e.ClientPoint); var lineFeature = Module1.SelectLineFeature(mapPoint); if (lineFeature != null) { var nearest = GeometryEngine.NearestPoint(lineFeature, mapPoint); lock (_lock) { _workingLocation = null; _lineFeature = lineFeature; if (_graphic != null) { _graphic.Dispose(); } _graphic = this.AddOverlay(nearest.Point, _pointSymbol.MakeSymbolReference()); _trackingMouseMove = TrackingState.CanTrack; } } else { lock (_lock) { _workingLocation = null; _lineFeature = null; if (_graphic != null) { _graphic.Dispose(); } _graphic = null; _trackingMouseMove = TrackingState.NotTracking; } } })); }
protected override async void OnToolMouseMove(MapViewMouseEventArgs e) { //All of this logic is to avoid unnecessarily updating the graphic position //for ~every~ mouse move. We skip any "intermediate" points in-between rapid //mouse moves. lock (_lock) { if (_trackingMouseMove == TrackingState.NotTracking) { return; } else { if (_workingLocation.HasValue) { _lastLocation = e.ClientPoint; return; } else { _lastLocation = e.ClientPoint; _workingLocation = e.ClientPoint; } } _trackingMouseMove = TrackingState.Tracking; } //The code "inside" the QTR will execute for all points that //get "buffered" or "queued". This avoids having to spin up a QTR //for ~every~ point of ~every mouse move. await QueuedTask.Run(() => { var symReference = _pointSymbol.MakeSymbolReference(); while (true) { System.Windows.Point?point; Polyline lineFeature = null; IDisposable graphic = null; lock (_lock) { point = _lastLocation; _lastLocation = null; _workingLocation = point; if (point == null || !point.HasValue) //No new points came in while we updated the overlay { _workingLocation = null; break; } else if (_lineFeature == null || _graphic == null) //conflict with the mouse down, //If this happens then we are done. A new line and point will be //forthcoming from the SketchCompleted callback { _trackingMouseMove = TrackingState.NotTracking; break; } lineFeature = _lineFeature; graphic = _graphic; } //update the graphic overlay var nearest = GeometryEngine.NearestPoint(lineFeature, MapView.Active.ClientToMap(point.Value)); this.UpdateOverlay(graphic, nearest.Point, symReference); } }); }