This is one way of finding the nearest geometry but it can be optimized. This sample assumes you are only checking against one layer and will select the closest graphic. The con for doing this is, you will be making async call on every graphic. You might want to refer to Buffer a Point and Intersect samples too. Another idea is to buffer the point returned by MapClick until you find geometries intersecting the buffered point. These intersecting geometries become your candidates for calling DistanceAsync. This may limit the number of async calls you make. At worse case, you may need to keep buffering the point only to find all geometries will intersect it, which means you will be calling DistanceAsync on all geometries anyway. I'm not sure how likely this scenario is but you have to remember too that there can be at most 1000 features returned for ArcGIS Server 10 or 500 for ArcGIS Server 9.31.
public MainPage()
{
InitializeComponent();
polygonLayer = this.MyMap.Layers["Polygon"] as FeatureLayer;
geometryService = new GeometryService("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
geometryService.DistanceCompleted += new EventHandler<DistanceEventArgs>(GeometryService_DistanceCompleted);
distanceParameter = new DistanceParameters()
{
DistanceUnit = LinearUnit.Kilometer,
Geodesic = true
};
}
FeatureLayer polygonLayer;
GeometryService geometryService;
DistanceParameters distanceParameter;
Graphic closestGraphic;
double distanceRecorded;
private void MyMap_MouseClick(object sender, Map.MouseEventArgs e)
{
closestGraphic = null;
distanceRecorded = 0;
if (polygonLayer != null && polygonLayer.Graphics != null && polygonLayer.Graphics.Count > 0)
{
int i = 0;
Graphic g = polygonLayer.Graphics;
geometryService.DistanceAsync(e.MapPoint, g.Geometry, distanceParameter, new object[]{polygonLayer.Graphics, i, e.MapPoint});
}
}
private void GeometryService_DistanceCompleted(object sender, DistanceEventArgs e)
{
object[] distanceParams = e.UserState as object[];
if (distanceParams != null && distanceParams.Length == 3 &&
distanceParams[0] is GraphicCollection && distanceParams[1] is int
&& distanceParams[2] is MapPoint)
{
GraphicCollection graphics = distanceParams[0] as GraphicCollection;
int index = (int)distanceParams[1];
MapPoint mp = distanceParams[2] as MapPoint;
if (closestGraphic == null || distanceRecorded > e.Distance)
{
distanceRecorded = e.Distance;
closestGraphic = graphics[index];
}
index++;
if (index < graphics.Count)
{
Graphic g = polygonLayer.Graphics[index];
geometryService.DistanceAsync(mp, g.Geometry, distanceParameter, new object[] { polygonLayer.Graphics, index, mp });
}
else
{
foreach (Graphic g in graphics)
{
if (g == closestGraphic)
g.Selected = true;
else
g.Selected = false;
}
}
}
}