Because 2.2 is not out yet I have extended the Draw class to create the circle just like it does with rectangle. The only thing is you have to call StartDrawCircle() add the eventing for drawing the circle. You will have to call EndDrawCircle to remove the events from the map. It will fire the DrawCompleted event on the base class when you MouseLeftButtonUp event happens to complete the circle. Enjoy.
public class MarkupModel : Draw
{
#region DrawCircle
private GraphicsLayer _circleDrawingLayer;
private MapPoint _circleCenter;
public void StartDrawCircle()
{
//end any previous circle drawing
EndDrawCircle();
if (_circleDrawingLayer == null)
_circleDrawingLayer = new GraphicsLayer();
Map.Layers.Add(_circleDrawingLayer);
Map.MouseLeftButtonDown += Map_MouseLeftButtonDown;
Map.MouseLeftButtonUp += Map_MouseLeftButtonUp;
Map.MouseMove += Map_MouseMove;
}
public void EndDrawCircle()
{
Map.Layers.Remove(_circleDrawingLayer);
Map.MouseLeftButtonDown -= Map_MouseLeftButtonDown;
Map.MouseMove -= Map_MouseMove;
Map.MouseLeftButtonUp -= Map_MouseLeftButtonUp;
}
public Graphic CreateCircle(MapPoint center, double radius)
{
int numPoints = 50;
//make sure the radius is a positive number
radius = Math.Abs(radius);
PointCollection ring = new PointCollection();
// 2PI = 360 degrees, +1 so that the end points meet
for (double i = 0; i < numPoints + 1; i++)
{
double theta = Math.PI * (i / (numPoints / 2));
var vertexLat = center.Y + (radius * Math.Sin(theta));
var vertexLng = center.X + (radius * Math.Cos(theta));
var point = new MapPoint(vertexLng, vertexLat);
ring.Add(point);
}
return new Graphic()
{
Geometry = new Polygon() { Rings = new System.Collections.ObjectModel.ObservableCollection<PointCollection>() { ring } },
Symbol = base.FillSymbol
};
}
#region Circle Event Handlers
void Map_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_circleCenter = Map.ScreenToMap(e.GetPosition(Map));
e.Handled = true; //need to do this or the map will allow drag
}
void Map_MouseMove(object sender, MouseEventArgs e)
{
if (_circleCenter == null)
return;
var radiusPoint = Map.ScreenToMap(e.GetPosition(Map));
if (radiusPoint != null)
{
//generate new circle points
var radius = _circleCenter.DistanceTo(radiusPoint);
var graphic = CreateCircle(_circleCenter, radius);
//don't replace the graphic each time because it will lead to flickering, just replace geometry
if (_circleDrawingLayer.Graphics.Count > 0)
_circleDrawingLayer.Graphics[0].Geometry = graphic.Geometry;
else
_circleDrawingLayer.Graphics.Add(graphic);
}
}
void Map_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_circleCenter = null;
if (_circleDrawingLayer == null || _circleDrawingLayer.Graphics.Count == 0)
return;
//only call the completed event when the polygon valid
var polyGraphic = _circleDrawingLayer.Graphics.FirstOrDefault();
if (polyGraphic != null && polyGraphic.Geometry.Extent.Width > 0)
{
DrawMode = ESRI.ArcGIS.Client.DrawMode.Polygon; //set the draw mode to eventing will work
var poly = polyGraphic.Geometry as ESRI.ArcGIS.Client.Geometry.Polygon;
foreach (var point in poly.Rings[0])
{
AddVertex(point);
}
CompleteDraw();
DrawMode = ESRI.ArcGIS.Client.DrawMode.None; //turn off the draw mode, it never happened
}
_circleDrawingLayer.ClearGraphics();
}
#endregion Circle Event Handlers
#endregion DrawCircle
}
You will need this extension function that I created to get the distance between two points
public static double DistanceTo(this MapPoint point1, MapPoint point2)
{
var a = (double)(point2.X - point1.X);
var b = (double)(point2.Y - point1.Y);
return Math.Sqrt(a * a + b * b);
}