6

Here is the XAML code:

<maps:Map x:Name="NearbyMap" 
                  Center="{Binding MapCenter, Mode=TwoWay}"
                  ZoomLevel="{Binding ZoomLevel, Mode=TwoWay}"
              >
        <maptk:MapExtensions.Children>
            <maptk:MapItemsControl Name="StoresMapItemsControl" ItemsSource="{Binding Treks}">
                <maptk:MapItemsControl.ItemTemplate>
                    <DataTemplate>
                        <maptk:Pushpin x:Name="RouteDirectionsPushPin" GeoCoordinate="{Binding Location}" Visibility="Visible" Content="test"/>
                    </DataTemplate>
                </maptk:MapItemsControl.ItemTemplate>
            </maptk:MapItemsControl>
            <maptk:UserLocationMarker x:Name="UserLocationMarker" Visibility="Visible" GeoCoordinate="{Binding MyLocation}"/>
        </maptk:MapExtensions.Children>
    </maps:Map>

xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
xmlns:maptk="clr-namespace:Microsoft.Phone.Maps.Toolkit;assembly=Microsoft.Phone.Controls.Toolkit"

PushPinModel has an attribute Location which is a GeoCoordinate. Treks is an ObservableCollection<PushPinModel>. I run this code and only the UserLocationMarker is displayed, which is my current location.

Rares Felecan
  • 358
  • 3
  • 17

2 Answers2

16

I finally make it work by using dependency property. I added a new class:

public static class MapPushPinDependency
{
    public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.RegisterAttached(
             "ItemsSource", typeof(IEnumerable), typeof(MapPushPinDependency),
             new PropertyMetadata(OnPushPinPropertyChanged));

    private static void OnPushPinPropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
    {
        UIElement uie = (UIElement)d;
        var pushpin = MapExtensions.GetChildren((Map)uie).OfType<MapItemsControl>().FirstOrDefault();
        pushpin.ItemsSource = (IEnumerable)e.NewValue;
    }


    #region Getters and Setters

    public static IEnumerable GetItemsSource(DependencyObject obj)
    {
        return (IEnumerable)obj.GetValue(ItemsSourceProperty);
    }

    public static void SetItemsSource(DependencyObject obj, IEnumerable value)
    {
        obj.SetValue(ItemsSourceProperty, value);
    }

    #endregion
}

And in the .xaml file I have added

xmlns:dp="clr-namespace:Treks.App.Util.DependencyProperties"

and now the .xaml file looks like this:

<maps:Map x:Name="NearbyMap" 
                  Center="{Binding MapCenter, Mode=TwoWay}"
                  ZoomLevel="{Binding ZoomLevel, Mode=TwoWay}"
                  dp:MapPushPinDependency.ItemsSource="{Binding Path=Treks}"
              >
        <maptk:MapExtensions.Children>
            <maptk:MapItemsControl Name="StoresMapItemsControl">
                <maptk:MapItemsControl.ItemTemplate>
                    <DataTemplate>
                        <maptk:Pushpin x:Name="PushPins" GeoCoordinate="{Binding Location}" Visibility="Visible" Content="test"/>
                    </DataTemplate>
                </maptk:MapItemsControl.ItemTemplate>
            </maptk:MapItemsControl>
            <maptk:UserLocationMarker x:Name="UserLocationMarker" Visibility="Visible" GeoCoordinate="{Binding MyLocation}"/>
        </maptk:MapExtensions.Children>
    </maps:Map>

Now all the pushpins are correctly rendered.

Rares Felecan
  • 358
  • 3
  • 17
  • Could you also provide code for the Page.xaml.cs - I don't know how I can bind the actual list of map items (i.e. `Tracks`) to the `Map` or `MapItemsControl` – Tobias Helbich Sep 24 '13 at 12:21
  • solved my problem, I couldn't access the MapItemsControl with the name: `ObservableCollection children = MapExtensions.GetChildren(NearbyMap); MapItemsControl mapItems = children.FirstOrDefault(x => x.GetType() == typeof(MapItemsControl)) as MapItemsControl; mapItems.ItemsSource = Treks;` – Tobias Helbich Sep 24 '13 at 12:59
3

The MapItemsControl is currently not yet MVVM bindable ( what I am aware off ). So best way is to set it's ItemsSource in the code behind of your view.

You can still use the collection defined in your ViewModel though! Options are:

  • through mvvm messaging pass along the collection from the viewmodel to the code behind of the view
  • use the datacontext of the view to access the collection, something like this: this.StoresMapItemsControl.ItemsSource = ServiceLocator.Current.GetInstance<MainViewModel>().Locations;
Depechie
  • 6,102
  • 24
  • 46