/// <summary> /// Synchronizes changes to the ApiViewModel's Results collection. The elements of that collection are assumed /// to implement IMappable (see the APIMASH_TomTom.TomTomCameraViewModel implementation for a sample reference). /// This code should require no changed regardless as long as the items in the Results collection implement IMappable. /// </summary> void Results_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { // only additions and wholesale reset of the ObservableCollection are currently supported switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (var item in e.NewItems) { IMappable mapItem = (IMappable)item; PointOfInterestPin poiPin = new PointOfInterestPin(mapItem); poiPin.Tap += async(s, e2) => { TheMap.HighlightPointOfInterestPin(DefaultViewModel.SelectedItem, false); TheMap.HighlightPointOfInterestPin(poiPin.PointOfInterest, true); await ProcessSelectedItem(item); }; TheMap.AddPointOfInterestPin(poiPin, mapItem.Position); } break; case NotifyCollectionChangedAction.Reset: TheMap.ClearPointOfInterestPins(); break; // case NotifyCollectionChangedAction.Remove: // // TODO: (optional) if your application allows items to be selectively removed from the view model // code to remove a single associated push pin will be required. // // // // break; // not implemented in this context // case NotifyCollectionChangedAction.Replace: // case NotifyCollectionChangedAction.Move: } }
public MainPage() { this.InitializeComponent(); // check to see if this is the first time application is being executed by checking for data in local settings. // After checking add some notional data as marker for next time app is run. This will be used to determine whether // to prompt the user (or not) that location services are not turned on for the app/system. Without this check, the // first time the app is run, it will provide a system prompt, and if that prompt is dismissed without granting // access the propmpt displayed by the application would also appear unnecessarily. _firstRun = ApplicationData.Current.LocalSettings.Values.Count == 0; if (_firstRun) { ApplicationData.Current.LocalSettings.Values.Add( new System.Collections.Generic.KeyValuePair <string, object>("InitialRunDate", DateTime.UtcNow.ToString())); } // whenever map view changes track center point and zoom level in page state TheMap.ViewChangeEnded += (s, e) => { _pageState.MapCenter = new LatLong(TheMap.TargetCenter.Latitude, TheMap.TargetCenter.Longitude); _pageState.Zoom = TheMap.TargetZoomLevel; }; // set the reference to the current map for the LeftPanel (note: using Element binding will not handle all of the page navigation scenarios) LeftPanel.Map = TheMap; // whenever the contents of left panel are refreshed, save the map coordinates that were in play as part of the page state LeftPanel.Refreshed += (s, e) => { _pageState.MapBox = new BoundingBox(TheMap.TargetBounds.North, TheMap.TargetBounds.South, TheMap.TargetBounds.West, TheMap.TargetBounds.East); }; // whenver a new item is selected in the left panel, update the map pins and save the item selected as part of the page state LeftPanel.ItemSelected += (s, e) => { TheMap.HighlightPointOfInterestPin(e.NewItem, true); TheMap.HighlightPointOfInterestPin(e.OldItem, false); this._pageState.SelectedItemId = e.NewItem == null ? null : e.NewItem.Id; }; // whenever a new location is selected from the SearchFlyout (this is NOT the Search charm) update the position accordingly SearchFlyout.LocationChanged += (s, e) => { GotoLocation(e.Position); SearchFlyout.Hide(); }; // manage SearchFlyout visibility/interaction this.Tapped += (s, e) => { if (SearchFlyout.IsOpen) { SearchFlyout.Hide(); e.Handled = true; } }; BottomAppBar.Opened += (s, e) => { SearchFlyout.Hide(); }; SearchFlyout.Tapped += (s, e) => { e.Handled = true; }; // allow type-to-search for Search charm SearchPane.GetForCurrentView().ShowOnKeyboardInput = true; // The BingMaps API allows use of a "session key" if the application leverages the Bing Maps control. By using the session // key instead of the API key, only one transaction is logged agains the key versus one transaction for every API call! This // code sets the key asynchronously and stored it as a resource so it's available when the REST API's are invoked. TheMap.Loaded += async(s, e) => { if (!Application.Current.Resources.ContainsKey("BingMapsSessionKey")) { Application.Current.Resources.Add("BingMapsSessionKey", await TheMap.GetSessionIdAsync()); } }; // register callback to reset (hide) the user's location, if location access is revoked while app is running _geolocator.StatusChanged += (s, a) => { this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() => { if (a.Status == PositionStatus.Disabled) { _locationMarker.Visibility = Visibility.Collapsed; } }) ); }; }
/// <summary> /// Dismiss current item's detail image /// </summary> private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e) { TheMap.HighlightPointOfInterestPin(DefaultViewModel.SelectedItem, false); DefaultViewModel.SelectedItem = null; }
public MainPage() { this.InitializeComponent(); // view model this.DefaultViewModel["PendingRefresh"] = false; // check to see if this is the first time application is being executed by checking for data in local settings. // After checking add some notional data as marker for next time app is run. This will be used to determine whether // to prompt the user (or not) that location services are not turned on for the app/system. Without this check, the // first time the app is run, it will provide a system prompt, and if that prompt is dismissed without granting // access the propmpt displayed by the application would also appear unnecessarily. _firstRun = ApplicationData.Current.LocalSettings.Values.Count == 0; if (_firstRun) { ApplicationData.Current.LocalSettings.Values.Add( new System.Collections.Generic.KeyValuePair <string, object>("InitialRunDate", DateTime.UtcNow.ToString())); } this.SizeChanged += (s, e) => { // determine if there's been a change in orientation that doesn't require notice that the map view has changed (e.g., app open, snapped mode transitions) if (_priorOrientation == ApplicationView.Value) { return; } _noRefreshRequiredViewChange = (_priorOrientation == ApplicationViewState.Snapped || ApplicationView.Value == ApplicationViewState.Snapped); _priorOrientation = ApplicationView.Value; VisualStateManager.GoToState(LeftPanel, ApplicationView.Value.ToString(), true); }; // whenever map view changes track center point and zoom level in page state TheMap.ViewChangeEnded += (s, e) => { // save new center/zoom for page state _pageState.MapCenter = new LatLong(TheMap.TargetCenter.Latitude, TheMap.TargetCenter.Longitude); _pageState.Zoom = TheMap.TargetZoomLevel; // ViewChangeEnded fires a bit too often, so retain bounding box to determine if the view truly has changed BoundingBox thisBox = new BoundingBox(TheMap.TargetBounds.North, TheMap.TargetBounds.South, TheMap.TargetBounds.West, TheMap.TargetBounds.East); // determine if view change should notify user of pending refresh requirement if (_retainRefreshRequiredViewChange) { this.DefaultViewModel["PendingRefresh"] = _pageState.PendingRefresh; } else if (_noRefreshRequiredViewChange) { this.DefaultViewModel["PendingRefresh"] = false; } else if (App.InitialMapResizeHasOccurred) { this.DefaultViewModel["PendingRefresh"] = (thisBox != _lastBox); } // update state variables _lastBox = thisBox; if (App.InitialMapResizeHasOccurred) { _noRefreshRequiredViewChange = false; } _retainRefreshRequiredViewChange = false; App.InitialMapResizeHasOccurred = true; }; // if refresh prompt is tapped, refresh the map RefreshPrompt.Tapped += async(s, e) => { await LeftPanel.Refresh(_lastBox); this.DefaultViewModel["PendingRefresh"] = false; }; // a tap on map will cause refresh is one is predicated TheMap.Tapped += async(s, e) => { if ((Boolean)this.DefaultViewModel["PendingRefresh"]) { await LeftPanel.Refresh(_lastBox); this.DefaultViewModel["PendingRefresh"] = false; } }; // set the reference to the current map for the LeftPanel (note: using Element binding will not handle all of the page navigation scenarios) LeftPanel.Map = TheMap; // whenever the contents of left panel are refreshed, save the map coordinates that were in play as part of the page state LeftPanel.Refreshed += (s, e) => { _pageState.MapBox = new BoundingBox(TheMap.TargetBounds.North, TheMap.TargetBounds.South, TheMap.TargetBounds.West, TheMap.TargetBounds.East); }; // whenver a new item is selected in the left panel, update the map pins and save the item selected as part of the page state LeftPanel.ItemSelected += (s, e) => { TheMap.HighlightPointOfInterestPin(e.NewItem, true); TheMap.HighlightPointOfInterestPin(e.OldItem, false); this._pageState.SelectedItemId = e.NewItem == null ? null : e.NewItem.Id; }; // whenever a new location is selected from the SearchFlyout (this is NOT the Search charm) update the position accordingly SearchFlyout.LocationChanged += (s, e) => { GotoLocation(e.Position); SearchFlyout.Hide(); }; // manage SearchFlyout visibility/interaction this.Tapped += (s, e) => { if (SearchFlyout.IsOpen) { SearchFlyout.Hide(); e.Handled = true; } }; BottomAppBar.Opened += (s, e) => { SearchFlyout.Hide(); }; SearchFlyout.Tapped += (s, e) => { e.Handled = true; }; // allow type-to-search for Search charm SearchPane.GetForCurrentView().ShowOnKeyboardInput = true; // The BingMaps API allows use of a "session key" if the application leverages the Bing Maps control. By using the session // key instead of the API key, only one transaction is logged agains the key versus one transaction for every API call! This // code sets the key asynchronously and stored it as a resource so it's available when the REST API's are invoked. TheMap.Loaded += async(s, e) => { if (!Application.Current.Resources.ContainsKey("BingMapsSessionKey")) { Application.Current.Resources.Add("BingMapsSessionKey", await TheMap.GetSessionIdAsync()); } }; }