using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.MapKit; // required
using MonoTouch.CoreLocation; // required
namespace MapKit01
{
/// <summary>
/// MapKit103
/// http://conceptdev.blogspot.com/2009/09/monotouch-mapkit-103.html
/// </summary>
public class Application
{
static void Main (string[] args)
{
try { // try-catch for debugging only
UIApplication.Main (args);
} catch (Exception ex)
{
Console.WriteLine("Main " + ex.Message);
}
}
}
/// <summary>
/// The name AppDelegate is referenced in the MainWindow.xib file.
/// It is a partial class that has a Register() attribute for MonoTouch
/// </summary>
public partial class AppDelegate : UIApplicationDelegate
{
MKReverseGeocoder geoCoder;
public CLLocation mylocation;
CLLocationManager locationManager;
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
mapType.ValueChanged += delegate {
if (mapType.SelectedSegment == 0)
mapView.MapType = MonoTouch.MapKit.MKMapType.Standard;
else if (mapType.SelectedSegment == 1)
mapView.MapType = MonoTouch.MapKit.MKMapType.Satellite;
else if (mapType.SelectedSegment == 2)
mapView.MapType = MonoTouch.MapKit.MKMapType.Hybrid;
};
textfieldLatitude.AllEditingEvents += delegate {
Console.WriteLine("alleditingevents");
};
textfieldLatitude.Ended += delegate { // move cursor to Longitude field
textfieldLongitude.BecomeFirstResponder();
};
textfieldLongitude.AllEditingEvents += delegate {
Console.WriteLine("alleditingevents");
};
textfieldLongitude.Ended += delegate { // hide keyboard
textfieldLongitude.ResignFirstResponder();
};
buttonCurrent.TouchDown += delegate { // reverse geocode CurrentLocation (from GPS)
Console.WriteLine("geoloc location set from LocationManager " + locationManager.Location.Coordinate.Latitude
+","+locationManager.Location.Coordinate.Longitude);
CLLocationCoordinate2D location2 = new CLLocationCoordinate2D(locationManager.Location.Coordinate.Latitude
,locationManager.Location.Coordinate.Longitude);
geoCoder = new MKReverseGeocoder(location2);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
};
buttonMap.TouchDown += delegate { // reverse geocode Map center point
Console.WriteLine("geoloc location set from MapView CenterCoordinate");
geoCoder = new MKReverseGeocoder(mapView.CenterCoordinate);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
};
buttonGeoloc.TouchDown += delegate { // reverse geocode Lat,Long typed by user
try
{
Console.WriteLine("geoloc location set in button " + textfieldLatitude.Text +","+ textfieldLongitude.Text);
CLLocationCoordinate2D location1 = new CLLocationCoordinate2D(
Convert.ToDouble(textfieldLatitude.Text),
Convert.ToDouble(textfieldLongitude.Text));
geoCoder = new MKReverseGeocoder(location1);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
}
catch (Exception e)
{
Console.WriteLine("buttonGeoloc.TouchDown EXCEPTION:" + e.Message);
// Probably invalid keyboard input, just reset for now...
textfieldLatitude.Text = "-33.867139";
textfieldLongitude.Text = "151.207114";
}
};
buttonGo.TouchDown += delegate { // move map to Lat,Long typed by user
mapView.SetCenterCoordinate(new CLLocationCoordinate2D(
Convert.ToDouble(textfieldLatitude.Text),
Convert.ToDouble(textfieldLongitude.Text)),true);
};
buttonGoCurrent.TouchDown += delegate { // move map to Current Location (from GPS)
CLLocationCoordinate2D location3 = new CLLocationCoordinate2D(locationManager.Location.Coordinate.Latitude
,locationManager.Location.Coordinate.Longitude);
mapView.SetCenterCoordinate(location3,true);
};
mapView.ShowsUserLocation = true;
mapView.MapType = MonoTouch.MapKit.MKMapType.Standard;
mapView.Delegate = new MapViewDelegate(this); // RegionChanged, GetViewForAnnotation
locationManager = new CLLocationManager();
locationManager.Delegate = new LocationManagerDelegate(mapView, this);
locationManager.StartUpdatingLocation();
// Perform the first ReverseGeocode as the app starts up! No reason, just because we can...
CLLocationCoordinate2D location = new CLLocationCoordinate2D(0,0);
location = new CLLocationCoordinate2D(-33.867139,151.207114);
Console.WriteLine("geoloc location set");
geoCoder = new MKReverseGeocoder(location);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
MyAnnotation a = new MyAnnotation(
new CLLocationCoordinate2D(-33.867139,151.207114)
, "Home"
, "is where the heart is"
);
Console.WriteLine("This adds a custom placemark in Sydney, Australia :)");
mapView.AddAnnotationObject(a);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
/// <summary>
/// MonoTouch definition seemed to work without too much trouble
/// </summary>
private class LocationManagerDelegate: CLLocationManagerDelegate
{
private MKMapView _mapview;
private AppDelegate _appd;
private int _count = 0;
public LocationManagerDelegate(MKMapView mapview, AppDelegate appd):base()
{
_mapview = mapview;
_appd=appd;
Console.WriteLine("Delegate created");
}
/// <summary>
/// Whenever the GPS sends a new location, update text in label
/// and increment the 'count' of updates AND reset the map to that location
/// </summary>
public override void UpdatedLocation (CLLocationManager manager, CLLocation newLocation, CLLocation oldLocation)
{
MKCoordinateSpan span = new MKCoordinateSpan(0.2,0.2);
MKCoordinateRegion region = new MKCoordinateRegion(newLocation.Coordinate,span);
_appd.mylocation = newLocation;
_mapview.SetRegion(region, true);
_appd.labelInfo.Text = "UserLocation (" + (_count++) + ") " + newLocation.Coordinate.Latitude + ", " + newLocation.Coordinate.Longitude;
Console.WriteLine("Location updated");
}
public override void Failed (CLLocationManager manager, NSError error)
{
_appd.labelInfo.Text = "Failed to find location";
Console.WriteLine("Failed to find location");
base.Failed (manager, error);
}
}
/// <summary>
/// MKAnnotation is an abstract class (in Objective C I think it's a protocol).
/// Therefore we must create our own implementation of it. Since all the properties
/// are read-only, we have to pass them in via a constructor.
/// </summary>
public class MyAnnotation : MKAnnotation
{
private CLLocationCoordinate2D _coordinate;
private string _title, _subtitle;
public override CLLocationCoordinate2D Coordinate {
get {
return _coordinate;
}
}
public override string Title {
get {
return _title;
}
}
public override string Subtitle {
get {
return _subtitle;
}
}
/// <summary>
/// custom constructor
/// </summary>
public MyAnnotation (CLLocationCoordinate2D coord, string t, string s) : base()
{
_coordinate=coord;
_title=t;
_subtitle=s;
}
}
/// <summary>
/// 'handler' for messages from ReverseGeocoderDelegate; pass in
/// reference to main window via ctor so we can chat with the UI
/// </summary>
public class GeoCoderDelegate : MKReverseGeocoderDelegate
{
AppDelegate _appd;
public GeoCoderDelegate (AppDelegate appd)
{
_appd = appd;
}
/// <summary>
/// When the reverse geocode finds a location, it calls this method
/// which puts the placemark on the map as an Annotation
/// </summary>
public override void FoundWithPlacemark (MKReverseGeocoder geocoder, MKPlacemark placemark)
{
Console.WriteLine("Found placemark in " + placemark.Country);
Console.WriteLine(placemark.SubThoroughfare +placemark.Thoroughfare +placemark.SubLocality +placemark.Locality +placemark.SubAdministrativeArea +placemark.AdministrativeArea + placemark.Country);
_appd.labelPlacemark.Text = placemark.SubThoroughfare+" "+placemark.Thoroughfare
+" " + placemark.Locality + " "+placemark.AdministrativeArea + " " + placemark.Country;
try
{
_appd.mapView.AddAnnotationObject(placemark);
}
catch (Exception ex)
{
Console.WriteLine("FoundWithPlacemark" + ex.Message);
}
}
/// <summary>
/// Exposed by MonoTouch, just override to make it work
/// </summary>
public override void FailedWithError (MKReverseGeocoder gc, NSError error)
{
_appd.labelPlacemark.Text = "Reverse Geocoder " + error.LocalizedDescription;
Console.WriteLine("Reverse Geocoder failed");
}
}
/// <summary>
///
/// </summary>
public class MapViewDelegate : MKMapViewDelegate
{
private AppDelegate _appd;
public MapViewDelegate (AppDelegate appd):base()
{
_appd = appd;
}
/// <summary>
/// When user moves the map, update lat,long text in label
/// </summary>
public override void RegionChanged (MKMapView mapView, bool animated)
{
Console.WriteLine("Region did change");
_appd.labelCurrent.Text = "Map Center " + mapView.CenterCoordinate.Latitude + ", " + mapView.CenterCoordinate.Longitude;
}
/// <summary>
/// Seems to work in the Simulator now
/// </summary>
public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
{
Console.WriteLine("attempt to get view for MKAnnotation "+annotation);
try
{
var anv = mapView.DequeueReusableAnnotation("thislocation");
if (anv == null)
{
Console.WriteLine("creating new MKAnnotationView");
var pinanv = new MKPinAnnotationView(annotation, "thislocation");
pinanv.AnimatesDrop = true;
pinanv.PinColor = MKPinAnnotationColor.Green;
pinanv.CanShowCallout = true;
anv = pinanv;
}
else
{
anv.Annotation = annotation;
}
return anv;
} catch (Exception ex)
{
Console.WriteLine("GetViewForAnnotation Exception " + ex);
return null;
}
}
}
}
}