正如在评论中提到的,最好的办法是绑定图钉集合。
Bing地图WPF控件是不是很宽容,当涉及到Binding
。不可能直接绑定到地图的Children
属性,因此需要采用不同的方法。
首先,创建一个包含您的地图UserControl
,我们就可以使用依赖属性做几乎代理绑定到Children
集合。
<UserControl ...
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"">
<Grid>
<m:Map CredentialsProvider="Your API Key Here"
x:Name="map"
MouseDoubleClick="Map_DoubleClicked"/>
</Grid>
这里是后台代码:
public partial class BindableMap : UserControl
{
public ObservableCollection<Pushpin> Pins
{
get { return (ObservableCollection<Pushpin>)GetValue(PinsProperty); }
set { SetValue(PinsProperty, value); }
}
// Using a DependencyProperty as the backing store for Pins. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PinsProperty =
DependencyProperty.Register("Pins", typeof(ObservableCollection<Pushpin>), typeof(BindableMap),
new PropertyMetadata(null, new PropertyChangedCallback(OnPinsChanged)));
private static void OnPinsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
BindableMap map = (BindableMap)d;
//If the pin collection changes, then reset the map view.
map.ClearMapPoints();
map.SubscribeToCollectionChanged();
}
private void ClearMapPoints()
{
map.Children.Clear();
}
private void SubscribeToCollectionChanged()
{
if (Pins != null)
Pins.CollectionChanged += Pins_CollectionChanged;
}
private void Pins_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//Remove the old pushpins
if (e.OldItems != null)
foreach (Pushpin pin in e.OldItems)
map.Children.Remove(pin);
//Add the new pushpins
if (e.NewItems != null)
foreach (Pushpin pin in e.NewItems)
map.Children.Add(pin);
}
public BindableMap()
{
InitializeComponent();
Pins = new ObservableCollection<Pushpin>();
}
private void Map_DoubleClicked(object sender, MouseButtonEventArgs e)
{
//Get the current position of the mouse.
Point point = Mouse.GetPosition(map);
//Create the pin.
Pushpin pin = new Pushpin();
pin.Location = map.ViewportPointToLocation(point);
//Add the pin to the map.
Pins.Add(pin);
}
}
这里要注意的一个事情是,View
,在这种情况下,UserControl
正在处理双击事件。这并不一定需要在视图模型中处理,因为我们将使用绑定来代替。
这是一个非常简单的视图模型:
public class BindableMapViewModel : PropertyChangedBase
{
private ObservableCollection<Pushpin> _Pushpins;
public ObservableCollection<Pushpin> Pushpins
{
get { return _Pushpins; }
set
{
_Pushpins = value;
NotifyOfPropertyChange();
}
}
public BindableMapViewModel()
{
Pushpins = new ObservableCollection<Pushpin>();
}
}
现在,所有剩下的就是用你的UserControl
在父Window
和Pushpins
视图模型集合绑定到Pins
依赖项属性。它看起来像这样:
<map:BindableMap Pins="{Binding Pushpins}"/>
而且你有它。
MVVM纯粹主义者在视图中没有代码。你只绑定到你的ViewModel,它有你的模型提供的点集合。 – SQLMason
您的ViewModel不必对您的视图一无所知。这是MVVM打破。正如@丹安德鲁斯所说,你必须在视图模型(或模型)上创建一个映射,并将其绑定到你的视图。 – Jose
而不是'EventToCommand',你可以创建附加的行为(使用几个附加的属性)。在该行为的代码中,您可以访问所有内容:双击事件(订阅它),映射(将其作为附加属性传递)和ViewModel(元素的DataContext或将它作为另一个附加属性传递)。 – Sinatr