Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM Windows Phone 8 - adding a collection of pushpins to a map

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.

like image 386
Rares Felecan Avatar asked May 07 '13 11:05

Rares Felecan


2 Answers

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.

like image 159
Rares Felecan Avatar answered Nov 02 '22 19:11

Rares Felecan


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;
like image 44
Depechie Avatar answered Nov 02 '22 18:11

Depechie