http://www.nikhilk.net/Silverlight-Locate-Me.aspx
While I was traveling around the country (see http://www.wiredwalkabout.com/), I would run Nikhil's application to see the result. For the most part, it always reported my location about 20 miles from where I really was, which I think is a problem with the web service used and not the code calling it.
http://api.hostip.info/get_html.php?position=true
Nikhil's current live sample has been updated, but it is still not at good as a GPS. The application source code is worth looking at in detail. He uses techniques that are more advanced than calling WebClient, and as a programmer it is interesting to know how to do same thing many different ways (viewing this link requires you have Silverlight 3 installed):
http://www.nikhilk.net/Content/Posts/SilverlightLocateMe/LocateMe.htm
This post is about integrating this functionality into the mapping application I am currently developing. I have decided to create a separate class of objects to mark my current location. I did this mainly because I wanted to use a different symbol to mark myself on the map -- like a "You Are Here" marker. I have extended this class to collect a time stamp, and this -- in combination with persistence -- can be used to track my movements.
I needed to modify the rendering code in order to display a different picture for this class. With this quick change, objects of type MyLocation now show a pushpin instead of a red rectangle.
public class MyLocation : PointOfInterest
{
public DateTime TimeStamp { get; set; }
public MyLocation()
: base()
{
TimeStamp = DateTime.Now;
}
#region Serializer Methods
public override XElement PersistTo(ModelSerializer oSerializer, XElement oSelf)
{
XElement oXElement = base.PersistTo(oSerializer, oSelf);
oXElement.Add(new XAttribute("TimeStamp", TimeStamp.ToString()));
return oXElement;
}
public override IMapModel RecoverFrom(ModelSerializer oSerializer, XElement oElement)
{
var oResult = base.RecoverFrom(oSerializer, oElement);
string sTimeStamp = oElement.Attribute("TimeStamp").Value;
TimeStamp = DateTime.Parse(sTimeStamp);
return oResult;
}
#endregion
}
The code to query the web service using WebClient follows. This is an asynchronous call that returns a string delimited by line feeds, so I used Nikhil's trick of reading from a stream to parse out and convert the Lat/Long information.
void RenderPoint(PointOfInterest oPOI)
{
if (oPOI is MyLocation)
{
Uri oSource = new Uri(@"Pushpin.png", UriKind.Relative);
var oBitmap = new BitmapImage(oSource);
var oImage = new Image() { Source = oBitmap, Width=23, Height=27 };
m_oLayer.AddChild(oImage, oPOI.Loc, PositionMethod.BottomCenter);
}
else
{
// Create a Rectangle Shape to Show as the "Pushpin"
// Set it's Size to 10x10
var oRect = new System.Windows.Shapes.Rectangle() { Fill = new SolidColorBrush(Colors.Red), Width = 10, Height = 10 };
// Add Rectangle to MapLayer
m_oLayer.AddChild(oRect, oPOI.Loc, PositionMethod.Center);
}
}
void WhereAmI()
{
WebClient oClient = new WebClient();
var oAddress = new Uri(@"http://api.hostip.info/get_html.php?position=true");
oClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(oClient_DownloadStringCompleted);
oClient.DownloadStringAsync(oAddress);
}
void oClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string sResult = e.Result;
using (StreamReader sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(sResult))))
{
try
{
sr.ReadLine();
sr.ReadLine();
double lat = 0;
TryParse<Double>(sr.ReadLine(), out lat);
double lng = 0;
TryParse<Double>(sr.ReadLine(), out lng);
var oPOI = new MyLocation() { Loc = new Location(lat, lng) };
m_oList.Add(oPOI);
RenderPoint(oPOI);
}
catch { }
}
MessageBox.Show(sResult);
}
No comments:
Post a Comment