MapOverlay binding not working

2019-02-15 02:07发布

问题:

I'm trying to get a map overlay working on Windows Phone 8 using an MVVM code structure. I can't seem to get the GeoCoordinate property of the MapOverlay to bind to my ViewModel properly and I can't work out why.

The XAML as stands is:

Header:

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

Code:

<maps:Map x:Name="Map"  ZoomLevel="6" Height="500" Width="500" CartographicMode="Terrain" Center="{Binding MapCenter, Converter={StaticResource GpsCoordinateConverter}, Mode=TwoWay}">
    <maps:Map.Layers>
        <maps:MapLayer>
            <maps:MapOverlay PositionOrigin="1,1"  GeoCoordinate="{Binding MapCenter, Converter={StaticResource GpsCoordinateConverter}, Mode=OneWay}">
                <Ellipse Fill="Blue" Height="20" Width="20" Opacity="50" />
            </maps:MapOverlay>
        </maps:MapLayer>
    </maps:Map.Layers>
</maps:Map>

The GpsCoordinateConverter is just a very simple class which changes the data type from my View Model into the System.Device.Location.GeoCoordinate that the map control expects. The center of the map binding is working fine, but the GeoCoordinate on the overlay will not bind and the blue circle just sits in the top left of the map.

I've verified the PropertyChanged event is firing for my model, both through debug and because the center of the map itself is updating, and even tried passing null to trigger all fields to no avail.

I've checked in debug and the property for the MapOverlay GeoCoordinate always seems to be null. I've tried adding the following to the code-behind which puts the circle where I want it, but I can't seem to get it to happen based on the event...

GpsCoordinateConverter converter = new GpsCoordinateConverter();
Map.Layers[0][0].GeoCoordinate = (GeoCoordinate)converter.Convert(((ViewModel.ReportViewModel)DataContext).MapCenter, typeof(GeoCoordinate), null, null);

Does anyone know why this would be or how to fix this? I'd prefer not to abandon the MVVM architecture for this.

回答1:

That's a limitation of the Silverlight XAML Parser. Objects initialized as part of XAML elements' properties will not participate in the same logical tree and as such don't have datacontext drilling down into them.

In order to databind the new Nokia Map control, use MapExtensions from the new Windows Phone Toolkit. For example here's how to create a PushPin in a specific GeoCoordinate using MapExtensions.

<maps:Map x:Name="Map" Grid.Row="1" Hold="OnMapHold">
    <maptk:MapExtensions.Children>
        <maptk:Pushpin x:Name="RouteDirectionsPushPin" Visibility="Collapsed"/>
        <maptk:MapItemsControl Name="StoresMapItemsControl">
            <maptk:MapItemsControl.ItemTemplate>
                <DataTemplate>
                    <maptk:Pushpin GeoCoordinate="{Binding GeoCoordinate}" Visibility="{Binding Visibility}" Content="{Binding Address}"/>
                </DataTemplate>
            </maptk:MapItemsControl.ItemTemplate>
        </maptk:MapItemsControl>
        <maptk:UserLocationMarker x:Name="UserLocationMarker" Visibility="Collapsed"/>
    </maptk:MapExtensions.Children>
</maps:Map>


回答2:

To fix this you need to implicitly tell your binding where to find the property, in MVVM Light world it would look like:

    <maps:MapOverlay GeoCoordinate="{Binding Main.CurrentLocation, Source={StaticResource Locator}}">
                            <Ellipse Fill="Blue" Height="20" Width="20" Opacity="50" />
                        </maps:MapOverlay>

also, you will need the dispatcher on the viewmodel to handle the ui change