|
using GalaSoft.MvvmLight;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using System.ServiceModel;
using System.Collections.ObjectModel;
using System;
using Microsoft.Maps.MapControl;
using GalaSoft.MvvmLight.Messaging;
using SLMapTest.Messages;
namespace SLMapTest.ViewModel
{
/// <summary>
/// This class contains properties that a View can data bind to.
/// <para>
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
/// </para>
/// <para>
/// You can also use Blend to data bind with the tool's support.
/// </para>
/// <para>
/// See http://www.galasoft.ch/mvvm/getstarted
/// </para>
/// </summary>
public class SLMapViewModel : ViewModelBase
{
//Since calls are asynchronous this will keep track of what we asked for
enum RequestType
{
FindRequest,
XRequest
}
bool showBusy;
RelayCommand findButton;
string findAddress;
string resultString;
RelayCommand<KeyEventArgs> keyUpCommand;
/// <summary>
/// Initializes a new instance of the SLMapViewModel class.
/// </summary>
public SLMapViewModel()
{
findButton = new RelayCommand(FindButtonClick);
//We want to know when user presses ENTER in the find address text field
keyUpCommand = new RelayCommand<KeyEventArgs>(TextFieldCharEntry);
//Register to receive message when user clicks on the map
Messenger.Default.Register<MapPointClickMsg>(this, MapClickHandler);
//And we can service bing geocode requests...
Messenger.Default.Register<GetStreetIntersectionMsg>(this, StreetIntersectionHandler);
}
#region private property
private BingGeocodeService.GeocodeServiceClient geocodeClient;
private BingGeocodeService.GeocodeServiceClient GeocodeClient
{
get
{
if (null == geocodeClient)
{
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
UriBuilder serviceUri = new UriBuilder("http://dev.virtualearth.net/webservices/v1/GeocodeService/GeocodeService.svc");
//Create the Service Client
geocodeClient = new BingGeocodeService.GeocodeServiceClient(binding, new EndpointAddress(serviceUri.Uri));
geocodeClient.GeocodeCompleted += new EventHandler<BingGeocodeService.GeocodeCompletedEventArgs>(GeocodeCompleted);
geocodeClient.ReverseGeocodeCompleted += new EventHandler<BingGeocodeService.ReverseGeocodeCompletedEventArgs>(geocodeClient_ReverseGeocodeCompleted);
}
return geocodeClient;
}
}
#endregion
#region Commanding
public ICommand FindButtonCommand
{
get { return findButton; }
}
void FindButtonClick()
{
//Make sure there's something there
if (findAddress.Length > 0)
{
//Clear out result string
resultString = "";
this.RaisePropertyChanged("ResultString");
GeocodeAddress(findAddress,RequestType.FindRequest);
}
}
public ICommand KeyUpCommand
{
get { return keyUpCommand; }
}
void TextFieldCharEntry(KeyEventArgs e)
{
//If it's ENTER key...
if (e.Key.Equals(Key.Enter))
{
if (findAddress != null && findAddress.Length > 0)
{
GeocodeAddress(findAddress,RequestType.FindRequest);
}
}
}
#endregion
#region data context
public string FindString
{
get { return findAddress; }
set { findAddress = value; }
}
public string ResultString
{
get { return resultString; }
set { resultString = value; }
}
public bool IsBusy
{
get { return showBusy; }
}
#endregion
#region service callback handler
private void GeocodeCompleted(object sender, BingGeocodeService.GeocodeCompletedEventArgs e)
{
//Clear busy flag...
showBusy = false;
this.RaisePropertyChanged("IsBusy");
string callResult = "";
Location xLocation = new Location();
string xStreets = "";
bool foundIntersection = false;
try
{
//Was the service able to parse it? And did it return anything?
if (e.Result.ResponseSummary.StatusCode != BingGeocodeService.ResponseStatusCode.Success ||
e.Result.Results.Count == 0)
{
if ((RequestType)e.UserState == RequestType.FindRequest)
callResult = "Can't find it!";
else
Messenger.Default.Send<StreetIntersectionResultMsg>(new StreetIntersectionResultMsg());
}
else
{
//What are we getting back?
if ((RequestType)e.UserState == RequestType.FindRequest)
{
Location geoLocation = new Location(e.Result.Results[0].Locations[0].Latitude, e.Result.Results[0].Locations[0].Longitude);
// Zoom the map to the desired location
Messenger.Default.Send<SetMapViewMsg>(new SetMapViewMsg() { CenterLocation = geoLocation });
}
else
{
xLocation = e.Result.Results[0].Locations[0];
xStreets = e.Result.Results[0].Address.AddressLine;
foundIntersection = true;
StreetIntersectionResultMsg result = new StreetIntersectionResultMsg();
result.IntersectionLocation = xLocation;
result.Intersection = xStreets;
result.StreetsIntersect = foundIntersection;
Messenger.Default.Send<StreetIntersectionResultMsg>(result);
}
}
}
catch
{
callResult = "Error processing request.";
}
resultString = callResult;
this.RaisePropertyChanged("ResultString");
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void geocodeClient_ReverseGeocodeCompleted(object sender, BingGeocodeService.ReverseGeocodeCompletedEventArgs e)
{
//Clear busy flag...
showBusy = false;
this.RaisePropertyChanged("IsBusy");
string callResult = "";
try
{
if (e.Result.ResponseSummary.StatusCode != BingGeocodeService.ResponseStatusCode.Success ||
e.Result.Results.Count == 0)
{
callResult = "Can't find it!";
}
else
{
//Publish results, somebody will know what to do with
ReverseGeocodeResultMsg resultMsg = new ReverseGeocodeResultMsg()
{
StreetAddress = e.Result.Results[0].Address.AddressLine,
City = e.Result.Results[0].Address.Locality,
State = e.Result.Results[0].Address.AdminDistrict
};
Messenger.Default.Send<ReverseGeocodeResultMsg>(resultMsg);
}
}
catch
{
callResult = "Error processing request.";
}
resultString = callResult;
this.RaisePropertyChanged("ResultString");
}
#endregion
#region private methods
private void GeocodeAddress(string address, RequestType reqType)
{
//Pack up a request
BingGeocodeService.GeocodeRequest request = new BingGeocodeService.GeocodeRequest();
request.Query = address;
// Don't raise exceptions.
request.ExecutionOptions = new BingGeocodeService.ExecutionOptions();
request.ExecutionOptions.SuppressFaults = true;
// Only accept results with high confidence.
request.Options = new BingGeocodeService.GeocodeOptions();
// Using ObservableCollection since this is the default for Silverlight proxy generation.
request.Options.Filters = new ObservableCollection<BingGeocodeService.FilterBase>();
BingGeocodeService.ConfidenceFilter filter = new BingGeocodeService.ConfidenceFilter();
filter.MinimumConfidence = BingGeocodeService.Confidence.High;
request.Options.Filters.Add(filter);
request.Credentials = new Credentials();
request.Credentials.ApplicationId = (string)App.Current.Resources["BingCredentialsKey"];
//Make the call...and set busy indicator
showBusy = true;
this.RaisePropertyChanged("IsBusy");
GeocodeClient.GeocodeAsync(request,reqType);
}
/// <summary>
///
/// </summary>
/// <param name="pointLocation"></param>
private void ReverseGeocode(Location pointLocation)
{
//Pack up a request
BingGeocodeService.ReverseGeocodeRequest request = new BingGeocodeService.ReverseGeocodeRequest();
// Don't raise exceptions.
request.ExecutionOptions = new BingGeocodeService.ExecutionOptions();
request.ExecutionOptions.SuppressFaults = true;
request.Location = pointLocation;
request.Credentials = new Credentials();
request.Credentials.ApplicationId = (string)App.Current.Resources["BingCredentialsKey"];
// Make asynchronous call to fetch the data... and set busy
showBusy = true;
this.RaisePropertyChanged("IsBusy");
GeocodeClient.ReverseGeocodeAsync(request);
}
#endregion
#region messenger handler
/// <summary>
/// Reverse geocode the location and pass the results back
/// </summary>
/// <param name="msgData"></param>
void MapClickHandler(MapPointClickMsg msgData)
{
ReverseGeocode(msgData.ClickLocation);
}
void StreetIntersectionHandler(GetStreetIntersectionMsg msgData)
{
GeocodeAddress(msgData.XStreetName + " & " + msgData.SegmentStreet + "," + msgData.XCity + "," + msgData.XState, RequestType.XRequest);
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.