0
votes

I'm developing a Desktop application that uses Bing maps and MVVM.

In the application, a user adds a Pushpin in the map by double clicking on it, the Pushpin location gets saved in an Event class and the Event class is sent through a WCF Service.

I would like to get the Latitude and Longitude from the Pushpin using data binding, however the compiler complains about DependencyProperty when I try to do that. I managed to set the Latitude and Longitude in the ViewModel from the View, however I don't know if it's valid in MVVM. I have seen examples using MapsItemControls but I don't understand them.

ViewModel

private Event evt;
public Event Evt
{
    get
    {
        return this.evt;
    }
    set
    {
        this.evt = value;
        OnPropertyChanged("Event");
    }
}

Map xaml

<m:Map Grid.RowSpan="5" Grid.Column="3" Margin="3" 
       Name="operatorMap"
       CredentialsProvider="Map_key" 
       Center="19.4000,-99.1333" 
       ZoomLevel="5" 
       MouseDoubleClick="SetPushpinLocation" />

CodeBehind

private MaintenanceFormViewModel viewModel = new MaintenanceFormViewModel();
private Pushpin pin = null;

public MainWindow()
{
    InitializeComponent();
    this.Loaded += (s, e) =>
    {
        this.DataContext = this.viewModel;
    };
}

private void SetPushpinLocation(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;
    Point mousePosition = e.GetPosition((UIElement)sender);
    Location pinLocation = operatorMap.ViewportPointToLocation(mousePosition);
    if (pin == null)
    {
        pin = new Pushpin();
        operatorMap.Children.Add(pin);
    }
    pin.Location = pinLocation;
    this.viewModel.Evt.Latitude = pinLocation.Latitude;
    this.viewModel.Evt.Longitude = pinLocation.Longitude;
}
2

2 Answers

3
votes

Bing Maps uses the attached property MapLayer.Position for positioning elements on the map.

Given a view model with a property of type Location

public class ViewModel : INotifyPropertyChanged
{
    private Location location;
    public Location Location
    {
        get { return location; }
        set
        {
            location = value;
            OnPropertyChanged("Location");
        }
    }

    ...
}

you can bind the position of a Pushpin like this:

<bm:Pushpin bm:MapLayer.Position="{Binding Location}"/>

Note that in the Windows Store App version of the Bing Maps SDK there seems to be a bug when you try to setup a binding in XAML. It says (still with Bing Maps SDK version 1.313.825.0)

Failed to assign to property 'Bing.Maps.MapLayer.Position'

You can however create a binding in code behind:

pushpin.SetBinding(MapLayer.PositionProperty,
    new Binding { Path = new PropertyPath("Location") });
0
votes

Personally, I'd add an attached property to the Bing map which would allow you to bind the lat/long to properties to your ViewModel. This would follow the MVVM pattern.

Google "attached property wpf" for a tutorial on attached properties, there are some good ones out there.

This is not to say that using code behind is bad: usually I get it working with code behind first, then port it into an attached property to adhere to the MVVM pattern, and for reusability and maintainability.

You mentioned an error related to dependecy properties. These are completely different to attached properties.

  • You add a dependency property to a user control that you write yourself.
  • You add an attached property to another 3rd party control you cannot alter or do not have the source code for. The rule of thumb is this: if you start with any code behind in a user control, you can shift it into an attached property to keep in line with the MVVM pattern.

Yes, attached properties are a bit of a learning curve, but persevere: this is one technique you will have to master before you can become an MVVM expert.