using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Maps.MapControl;
namespace SilverlightMap.ViewModel
{
public class SearchViewModel : ViewModelBase
private const double DefaultRadius = 20.0;
private double _radius;
public SearchViewModel()
SearchCommand = new RelayCommand<string>(Search);
Radius = DefaultRadius;
}
public double Radius
get { return _radius; }
set
_radius = value;
RaisePropertyChanged("Radius");
public Location CurrentLocation { get; set; }
public RelayCommand<string> SearchCommand { get; private set; }
private void Search(string searchText)
//todo appeler notre service de recherche utilisant le searchText et la CurrentLocation
< UserControl
x:Class="SilverlightMap.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:BingMap="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight"
mc:Ignorable="d"
d:DesignWidth="640"
d:DesignHeight="480">
< BingMap : Map
MouseDoubleClick="MyMap_OnMouseDoubleClick"
Grid.Row="1"
Grid.Column="1"
Grid.RowSpan="2"
Grid.ColumnSpan="2"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center"
IsTabStop="false"
x:Name="myMap"
CredentialsProvider="Votre Clef"
Mode="AerialWithLabels"
Center="-26.04740,132.45890"
ZoomLevel="5">
</ BingMap : Map >
< Slider
Margin="30"
Minimum="1"
Maximum="50"
Value="{Binding Radius, Mode=TwoWay}" />
< Button
x:Name="SearchButton"
cmd:ButtonBaseExtensions.Command="{Binding SearchCommand}"
cmd:ButtonBaseExtensions.CommandParameter="{Binding ElementName=SearchTextBox, Path=Text}"
Width="22"
Height="22"
/// <summary>
/// Handles the OnMouseDoubleClick event of the MyMap control.
/// </summary>
/// <param name="sender"> The source of the event. </param>
/// <param name="e"> The <see cref="Microsoft.Maps.MapControl.MapMouseEventArgs"/> instance
/// containing the event data. </param>
private void MyMap_OnMouseDoubleClick(object sender, MapMouseEventArgs e)
var location = myMap.ViewportPointToLocation(e.ViewportPoint);
_searchViewModel.CurrentLocation = location;
AddCircle(_searchViewModel.CurrentLocation, _searchViewModel.Radius, .5);
private void AddCircle(Location location, double radius, double opacity)
var polygon = new MapPolygon
Fill = new SolidColorBrush(Colors.Green),
Stroke = new SolidColorBrush(Colors.Blue),
StrokeThickness = 5,
Opacity = opacity,
Locations = DrawACircle(location, radius)
};
myMap.Children.Clear();
myMap.Children.Add(polygon);
public LocationCollection DrawACircle(Location location, double radius)
var locations = new LocationCollection();
const double earthRadius = GeoCodeCalc.EarthRadiusInMiles;
var latitude = GeoCodeCalc.ToRadian(location.Latitude);
//radians
var longitude = GeoCodeCalc.ToRadian(location.Longitude);
var d = radius / earthRadius;
// d = angular distance covered on earths surface
for (var x = 0; x <= 360; x++)
var brng = GeoCodeCalc.ToRadian(x); //radians
var latRadians = Math.Asin(Math.Sin(latitude) *
Math.Cos(d) + Math.Cos(latitude) *
Math.Sin(d) *
Math.Cos(brng));
var lngRadians = longitude +
Math.Atan2(Math.Sin(brng) * Math.Sin(d) * Math.Cos(latitude),
Math.Cos(d) - Math.Sin(latitude) * Math.Sin(latRadians));
var pt = new Location(180.0 * latRadians / Math.PI, 180.0 * lngRadians / Math.PI);
locations.Add(pt);
return locations;
using System;
namespace SilverlightMap
public static class GeoCodeCalc
public const double EarthRadiusInMiles = 3956.0;
public const double EarthRadiusInKilometers = 6367.0;
public static double ToRadian(double val)
return val*(Math.PI/180);
public static double DiffRadian(double val1, double val2)
return ToRadian(val2) - ToRadian(val1);
///<summary>
/// Calculate the distance between two geocodes. Defaults to using Miles.
///</summary>
public static double CalcDistance(double lat1, double lng1, double lat2, double lng2)
return CalcDistance(lat1, lng1, lat2, lng2, GeoCodeCalcMeasurement.Miles);
/// Calculate the distance between two geocodes.
public static double CalcDistance(double lat1, double lng1, double lat2, double lng2, GeoCodeCalcMeasurement m)
var radius = EarthRadiusInMiles;
if (m == GeoCodeCalcMeasurement.Kilometers)
radius = EarthRadiusInKilometers;
return radius*2*
Math.Asin(Math.Min(1,
Math.Sqrt((Math.Pow(Math.Sin((DiffRadian(lat1, lat2))/2.0), 2.0) +
Math.Cos(ToRadian(lat1))*Math.Cos(ToRadian(lat2))*
Math.Pow(Math.Sin((DiffRadian(lng1, lng2))/2.0), 2.0)))));
public enum GeoCodeCalcMeasurement
Miles = 0,
Kilometers = 1
public partial class MainPage : UserControl
private readonly SearchViewModel _searchViewModel;
public MainPage()
InitializeComponent();
_searchViewModel = new SearchViewModel();
_searchViewModel.PropertyChanged += (sender, args) =>
if (args.PropertyName == "Radius")
AddCircle(_searchViewModel.CurrentLocation,
_searchViewModel.Radius,
.5);
DataContext = _searchViewModel;