如何使用 MVVM 在 WPF 中绑定图钉位置?

How can I bind Pushpin location in WPF using MVVM?

我正在开发一个使用 Bing 地图和 MVVM 的桌面应用程序。

在应用程序中,用户通过双击在地图中添加图钉,图钉位置保存在事件 class 中,事件 class 通过 WCF 服务发送.

我想使用数据绑定从图钉获取纬度和经度,但是当我尝试这样做时编译器抱怨 DependencyProperty。 我设法在 View 的 ViewModel 中设置了纬度和经度,但是我不知道它在 MVVM 中是否有效。我看过使用 MapsItemControls 的示例,但我不理解它们。

视图模型

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

地图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" />

代码隐藏

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;
}

就我个人而言,我会在 Bing 映射中添加一个附加的 属性,这样您就可以将 lat/long 绑定到 ViewModel 的属性。这将遵循 MVVM 模式。

Google "attached property wpf" 有关附加属性的教程,那里有一些不错的教程。

这并不是说使用代码隐藏是不好的:通常我会先使用代码隐藏,然后将其移植到附加的 属性 以遵守 MVVM 模式,并实现可重用性和可维护性.

您提到了与依赖属性相关的错误。这些与附加属性完全不同。

  • 您将 dependency property 添加到您自己编写的用户控件。
  • 您将 attached property 添加到另一个您无法更改或没有其源代码的第 3 方控件。 经验法则是:如果您从用户控件中隐藏的任何代码开始,您可以将其转移到附加的 属性 以与 MVVM 模式保持一致。

是的,附加属性有点学习曲线,但要坚持:这是您在成为 MVVM 专家之前必须掌握的一项技术。

Bing 地图使用附加的 属性 MapLayer.Position 在地图上定位元素。

给定一个 属性 类型为 Location

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

    ...
}

您可以像这样绑定图钉的位置:

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

请注意,在 Windows 商店应用版本的 Bing Maps SDK 中,当您尝试在 XAML 中设置绑定时,似乎有 a bug。它说(仍然使用 Bing Maps SDK 版本 1.313.825.0)

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

但是您可以在后面的代码中创建绑定:

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