Assuming @NathanCastle1 is correct, which is what I also assume and why I asked about what is in the Xaml. I'm going to go out on a limb and assume the DataContext is being set in the Xaml also. However, without seeing the Xaml I cannot be sure exactly what is being done but I am going with this assumption.
One nice MVVM approach to adding functionality, imo, is using TriggerActions. Especially if you are not using an external library to handle Commanding and Eventing
Based on the code you have above we could create an Action that handles the GeoViewTapped and then creates the point.
public class CreatePointAction : TriggerAction<MapView>
{
private static bool _doubleTapped;
protected override void OnAttached()
{
base.OnAttached();
if (!(AssociatedObject is MapView mapView)) return;
//This seems silly to me, but a GeoViewDoubleTapped fires both a tapped and a double tapped.
//This indicate was double tapped
mapView.GeoViewDoubleTapped += (s, e) => { _doubleTapped = true; };
}
protected override async void Invoke(object parameter)
{
await Task.Delay(250);
if (_doubleTapped)
{
_doubleTapped = false;
return;
}
if (!(AssociatedObject is MapView mapView)) return;
if (!(parameter is GeoViewInputEventArgs args)) return;
//I'm just going to assume only the one layer
var graphicsOverlay = mapView.GraphicsOverlays.FirstOrDefault();
if ( graphicsOverlay == null ) return;
AddPoint(graphicsOverlay, args.Location);
}
private void AddPoint(GraphicsOverlay graphicsOverlay, MapPoint mapPoint)
{
var pointSymbol = new SimpleMarkerSymbol
{
Style = SimpleMarkerSymbolStyle.X,
Color = System.Drawing.Color.Red,
Size = 10.0,
Outline = new SimpleLineSymbol
{
Style = SimpleLineSymbolStyle.Solid, Color = System.Drawing.Color.Red, Width = 2.0
}
};
// Create a point graphic with the geometry and symbol.
var pointGraphic = new Graphic(mapPoint, pointSymbol);
// Add the point graphic to graphics overlay.
graphicsOverlay.Graphics.Add(pointGraphic);
}
}
To wire this in we add the Action as an EventTrigger in our MapView definition
<esri:MapView x:Name="MapView" Map="{Binding Map}" GraphicsOverlays="{Binding GraphicsOverlays}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="GeoViewTapped">
<local:CreatePointAction></local:CreatePointAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</esri:MapView>
Similar to what you are already doing you can setup the view point in the View constructor. But we do not need to instantiate the VM, this was done and we are not using the VM in any code in the code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MapPoint mapCenterPoint = new MapPoint(-117.6709, 35.6225, SpatialReferences.Wgs84);
MainMapView.SetViewpoint(new Viewpoint(mapCenterPoint, 100000));
}
}
And in the ViewModel the map initialization can be done as before
public class MapViewModel
{
protected GraphicsOverlay EditGraphicsOverlay { get; } = new GraphicsOverlay { Id = nameof(EditGraphicsOverlay) };
public MapViewModel()
{
SetupMap();
AddGraphicsOverlays();
}
private void SetupMap()
{
// Create a new map with a 'topographic vector' basemap.
Map = new Map(BasemapStyle.ArcGISTopographic);
}
private void AddGraphicsOverlays()
{
if (!GraphicsOverlays.Contains(EditGraphicsOverlay))
{
GraphicsOverlays.Add(EditGraphicsOverlay);
}
}
}
With that we should have everything wired up. There is no functional code in code behind all logic is in the Action and ViewModel. The Action could be reused in another project without need to change anything, just include the definition in the MapView xaml
Thanks,
-Joe