Reputation: 2877
I can't seem to get my head around this pushpin binding and I need some more help.
I have the follow code to parse from XML and split a coordinate string in Lat, Lon and Alt. What I want to do is to display these points as pushpins on my bing maps.
I thought that by creating a new object of Geocoordinates in Location
I could then bind that to my pushpin location, but nothing is displayed. Where am I going wrong?
namespace Pushpins_Itemsource
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
WebClient busStops = new WebClient();
busStops.DownloadStringCompleted += new DownloadStringCompletedEventHandler(busStops_DownloadStringCompleted);
busStops.DownloadStringAsync(new Uri("http://www.domain/source.xml"));
}
void busStops_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;
var busStopInfo = XDocument.Load("Content/BusStops2.xml");
var Transitresults = from root in busStopInfo.Descendants("Placemark")
let StoplocationE1 = root.Element("Point").Element("coordinates")
let nameE1 = root.Element("name")
select new TransitVariables
(StoplocationE1 == null ? null : StoplocationE1.Value,
nameE1 == null ? null : nameE1.Value);
}
// Add properties to your class
public class TransitVariables
{
// Add a constructor:
public TransitVariables(string stopLocation, string name)
{
this.StopLocation = stopLocation;
this.Name = name;
if (!string.IsNullOrEmpty(StopLocation))
{
var items = stopLocation.Split(',');
this.Lon = double.Parse(items[0]);
this.Lat = double.Parse(items[1]);
this.Alt = double.Parse(items[2]);
}
}
public string StopLocation { get; set; }
public string Name { get; set; }
public double Lat { get; set; }
public double Lon { get; set; }
public double Alt { get; set; }
}
public class TransitViewModel
{
ObservableCollection<TransitVariables> Transitresults ;
public ObservableCollection<TransitVariables> TransitCollection
{
get { return Transitresults; }
}
}
}
}
XAML looks like this.
<my:Map ZoomLevel="6" Height="500" HorizontalAlignment="Left" Margin="0,6,0,0" CopyrightVisibility="Collapsed" LogoVisibility="Collapsed" Name="Map" VerticalAlignment="Top" Width="456">
<my:MapItemsControl ItemsSource="{Binding TransitVariables}" Height="494">
<my:MapItemsControl.ItemTemplate>
<DataTemplate>
<my:Pushpin Location="{Binding Location}" />
</DataTemplate>
</my:MapItemsControl.ItemTemplate>
</my:MapItemsControl>
</my:Map>
Upvotes: 0
Views: 2253
Reputation: 46813
From the code you've posted, it looks like the issue is that the ItemsSource for MapsItemsControl is not databound to a collection. It's bound to a type.
Okay, Databinding doesn't really work unless you define a DataContext etc. You're sort of mixing and matching paradigms here. I think it would be good to learn MVVM and Databinding at somepoint, but for now, I think it's okay to just do a quick and dirty approach.
The easiest way to get this working is to just assign the ItemSource.
To do this, first name your MapsItemControl, so you can access it in the codebheind.
<my:Map ZoomLevel="6" Height="500" HorizontalAlignment="Left" Margin="0,6,0,0" CopyrightVisibility="Collapsed" LogoVisibility="Collapsed" Name="Map" VerticalAlignment="Top" Width="456">
<my:MapItemsControl x:Name="RhysMapItems" ItemsSource="{Binding TransitVariables}" Height="494">
<my:MapItemsControl.ItemTemplate>
<DataTemplate>
<my:Pushpin Location="{Binding Location}" />
</DataTemplate>
</my:MapItemsControl.ItemTemplate>
</my:MapItemsControl>
Inside your download string complete handler, you should be able to do this:
void busStops_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;
var busStopInfo = XDocument.Load("Content/BusStops2.xml");
var Transitresults = from root in busStopInfo.Descendants("Placemark")
let StoplocationE1 = root.Element("Point").Element("coordinates")
let nameE1 = root.Element("name")
select new TransitVariables
(StoplocationE1 == null ? null : StoplocationE1.Value,
nameE1 == null ? null : nameE1.Value);
// This should bind the itemsource properly
// Should use Dispatcher actually...see below
RhysMapItems.ItemsSource = Transitresults.ToList();
}
Now, the one caveat here, is that it's very likely that your DownloadStringCompleted handler will be invoked on a different thread than the UI thread.
In which case you'll need to make use of the Dispatcher.BeginInvoke() to modify the ItemSource property.
this.RootVisual.Dispatcher.BeginInvoke( _=> { RhysMapItems.ItemsSource = Transitresults.ToList();});
Upvotes: 1