Click here to Skip to main content
15,881,882 members
Articles / Hosted Services / Azure

Exploring Opportunities for the Cloud: Part 2

Rate me:
Please Sign up or sign in to vote.
4.91/5 (7 votes)
20 Jan 2011CPOL18 min read 23K   210   8  
A series of articles exploring Azure development featuring Bing Maps and phone.
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions