namespace DevExpress.DevAV.Presenters { using System; using System.Collections.Generic; using System.Text.RegularExpressions; using DevExpress.DevAV; using DevExpress.DevAV.ViewModels; using DevExpress.XtraMap; using DevExpress.XtraMap.Services; public abstract class RouteMapPresenter : BasePresenter where TEntity : class where TViewModel : class, IRouteMapViewModel { MapControl mapControlCore; Action updateUIActionCore; Action> updateRouteListActionCore; public RouteMapPresenter(MapControl mapControl, TViewModel viewModel, Action updateUIAction, Action> updateRouteList) : base(viewModel) { this.mapControlCore = mapControl; this.updateUIActionCore = updateUIAction; this.updateRouteListActionCore = updateRouteList; if(MapControl != null) { BindMap(); SubscribeRouteProviderEvents(); } SubscribeViewModelEvents(); } protected override void OnDisposing() { if(MapControl != null) UnsubscribeRouteProviderEvents(); UnsubscribeViewModelEvents(); this.updateUIActionCore = null; this.updateRouteListActionCore = null; this.mapControlCore = null; base.OnDisposing(); } public MapControl MapControl { get { return mapControlCore; } } protected ImageLayer TilesLayer { get { return (ImageLayer)(MapControl.Layers[0]); } } protected InformationLayer GeoCodeLayer { get { return (InformationLayer)(MapControl.Layers[1]); } } protected InformationLayer RouteLayer { get { return (InformationLayer)(MapControl.Layers[3]); } } protected BingMapDataProvider TilesProvider { get { return (BingMapDataProvider)TilesLayer.DataProvider; } } protected BingGeocodeDataProvider GeoCodeProvider { get { return (BingGeocodeDataProvider)GeoCodeLayer.DataProvider; } } protected BingRouteDataProvider RouteProvider { get { return (BingRouteDataProvider)RouteLayer.DataProvider; } } IZoomToRegionService zoomService; void BindMap() { TilesProvider.BingKey = MapViewModelBase.WinBingKey; RouteProvider.BingKey = MapViewModelBase.WinBingKey; GeoCodeProvider.BingKey = MapViewModelBase.WinBingKey; // this.zoomService = ((IServiceProvider)MapControl).GetService(typeof(IZoomToRegionService)) as IZoomToRegionService; } protected virtual void SubscribeRouteProviderEvents() { GeoCodeProvider.LocationInformationReceived += GeoCodeProvider_LocationInformationReceived; RouteProvider.RouteCalculated += RouteProvider_RouteCalculated; RouteProvider.LayerItemsGenerating += RouteProvider_LayerItemsGenerating; } protected virtual void SubscribeViewModelEvents() { ViewModel.UpdateRoute += ViewModel_UpdateRoute; ViewModel.PointAChanged += ViewModel_PointAChanged; ViewModel.PointBChanged += ViewModel_PointBChanged; ViewModel.TravelModeChanged += ViewModel_TravelModeChanged; } protected virtual void UnsubscribeRouteProviderEvents() { GeoCodeProvider.LocationInformationReceived -= GeoCodeProvider_LocationInformationReceived; RouteProvider.RouteCalculated -= RouteProvider_RouteCalculated; RouteProvider.LayerItemsGenerating -= RouteProvider_LayerItemsGenerating; } protected virtual void UnsubscribeViewModelEvents() { ViewModel.UpdateRoute -= ViewModel_UpdateRoute; ViewModel.PointAChanged -= ViewModel_PointAChanged; ViewModel.PointBChanged -= ViewModel_PointBChanged; ViewModel.TravelModeChanged -= ViewModel_TravelModeChanged; } void ViewModel_UpdateRoute(object sender, EventArgs e) { UpdateUI(GetViewModelEntity()); } protected void ViewModel_EntityChanged(object sender, System.EventArgs e) { UpdateUI(GetViewModelEntity()); } protected abstract TEntity GetViewModelEntity(); void ViewModel_TravelModeChanged(object sender, System.EventArgs e) { RouteProvider.RouteOptions.Mode = ViewModel.TravelMode; UpdateRoute(); } MapPushpin PointAPin { get; set; } void ViewModel_PointAChanged(object sender, System.EventArgs e) { if(PointAPin == null) PointAPin = new MapPushpin() { Text = "A" }; PointAPin.Location = ViewModel.PointA.ToGeoPoint(); } MapPushpin PointBPin { get; set; } void ViewModel_PointBChanged(object sender, System.EventArgs e) { if(PointBPin == null) PointBPin = new MapPushpin() { Text = "B" }; PointBPin.Location = ViewModel.PointB.ToGeoPoint(); } void RouteProvider_RouteCalculated(object sender, BingRouteCalculatedEventArgs e) { if(e.Error != null || e.Cancelled || e.CalculationResult == null || e.CalculationResult.ResultCode != RequestResultCode.Success) return; ProcessRouteResult(e.CalculationResult.RouteResults[0]); } void GeoCodeProvider_LocationInformationReceived(object sender, LocationInformationReceivedEventArgs e) { if(e.Error != null || e.Cancelled || e.Result == null || e.Result.ResultCode != RequestResultCode.Success) return; LocationInformation[] locations = e.Result.Locations; if(locations.Length > 0) { LocationInformation loc = locations[0]; ViewModel.PointB = new Address() { Line = loc.Address.FormattedAddress, Latitude = loc.Location.Latitude, Longitude = loc.Location.Longitude, }; } } void RouteProvider_LayerItemsGenerating(object sender, LayerItemsGeneratingEventArgs args) { var items = args.Items; for(int i = 0; i < items.Length; i++) { MapPushpin pushpin = items[i] as MapPushpin; if(pushpin != null) pushpin.Visible = false; } AddRoutePoints(); } void AddRoutePoints() { RouteLayer.Data.Items.Clear(); RouteLayer.Data.Items.Add(PointAPin); RouteLayer.Data.Items.Add(PointBPin); } void ProcessRouteResult(BingRouteResult routeResult) { ViewModel.RouteDistance = routeResult.Distance; ViewModel.RouteTime = routeResult.Time; List routePoints = new List(); foreach(BingRouteLeg leg in routeResult.Legs) foreach(BingItineraryItem item in leg.Itinerary) routePoints.Add(new RoutePoint(item)); UpdateRouteList(routePoints); zoomService.ZoomTo(ViewModel.PointA, ViewModel.PointB); } void UpdateRouteList(List routePoints) { if(updateRouteListActionCore != null) updateRouteListActionCore(routePoints); } void UpdateRoute() { List points = new List(); points.Add(new RouteWaypoint("Point A", ViewModel.PointA.ToGeoPoint())); points.Add(new RouteWaypoint("Point B", ViewModel.PointB.ToGeoPoint())); RouteProvider.CalculateRoute(points); } void UpdateUI(TEntity entity) { if(entity == null) return; if(updateUIActionCore != null) updateUIActionCore(entity); MapControl.CenterPoint = ViewModel.PointA.ToGeoPoint(); AddRoutePoints(); UpdateRoute(); } } public sealed class RoutePoint { static Regex removeTagRegex = new Regex(@"<[^>]*>", RegexOptions.Compiled); BingItineraryItem item; public RoutePoint(BingItineraryItem item) { this.item = item; ManeuverInstruction = removeTagRegex.Replace(item.ManeuverInstruction, string.Empty); double itemDistance = item.Distance; Distance = (itemDistance > 0.9) ? String.Format("{0:0} mi", Math.Ceiling(itemDistance)) : String.Format("{0:0} ft", Math.Ceiling(itemDistance * 52.8) * 100); } public BingManeuverType Maneuver { get { return item.Maneuver; } } public string ManeuverInstruction { get; private set; } public string Distance { get; private set; } } }