我正在开发一个Xamarin.Forms应用程序,它使用一个显示Map的页面。XAML是:
<maps:Map x:Name="Map">
...
</maps:Map>
我知道可以从页面的代码隐藏访问Map,如下所示:
var position = new Position(37.79762, -122.40181);
Map.MoveToRegion(new MapSpan(position, 0.01, 0.01));
Map.Pins.Add(new Pin
{
Label = "Xamarin",
Position = position
});
但是,由于此代码会破坏应用的MVVM架构,因此我更愿意从ViewModel访问Map
对象,而不是直接从View/页面访问--要么像上面的代码那样直接使用它,要么通过数据绑定到它的属性。
有人知道怎么做吗?
6条答案
按热度按时间5ssjco0h1#
如果您不想破坏MVVM模式,但仍然能够从ViewModel访问Map对象,则可以使用ViewModel中的属性公开Map示例,并从View绑定到该示例。
您的代码结构应该如下所述。
视图模型:
视图(在本例中,我使用的是
ContentPage
,但您可以使用任何您喜欢的视图):我没有展示如何实现,但是上面的代码只有在ViewModel是视图的
BindingContext
时才能工作。jecbmhm32#
创建一个新的控件,比如说
BindableMap
,它继承自Map并执行绑定更新,而原始的Map
内部缺少这些。Pins
属性和当前的MapSpan
。显然,您可以将自己的特殊需要添加到此控件中。之后您所要做的就是将ObservableCollection<Pin>
类型的属性添加到ViewModel中,并将其绑定到XAML中BindableMap
的PinsSource属性。下面是绑定Map:
备注:
PinsSource
属性添加成员时更新原始的Pins
属性,我将PinsSource
声明为ObservableCollection<Pin>
,并订阅了它的CollectionChanged
事件。显然,如果只想更改绑定属性的整个值,可以将其定义为IList
。关于这个问题的前两个答案,我的最后一句话是:
尽管将View控件作为ViewModel属性使我们不必在代码后面编写业务逻辑,但它仍然让人感觉有点笨拙。在我看来,MVVM的VM部分的全部要点(至少是其中的一个关键点)是它与V完全分离和解耦。而上述答案中提供的解决方案实际上是这样的:
将View控件插入ViewModel的中心。
我认为这样做,你不仅打破了MVVM的模式,而且你打破了它的心!
9ceoxa923#
我有两个选择,对我有效,对你也有帮助。
1.您可以将静态
Xamarin.Forms.Maps Map
属性添加到您的ViewModel
,并在设置绑定上下文后,在视图示例化期间设置此静态属性,如下所示:这将允许您在ViewModel中访问Map。
1.您可以在绑定期间将Map从视图传递到ViewModel,例如:
并从ViewModel的命令中获取Map。
egmofgnx4#
是的,
Map.Pins
是不可绑定的,但是有ItemsSource
,它很容易使用。因此,仅对于引脚,MVVM 无需任何自定义控制即可完成。但
Map.MoveToRegion()
(和要读取的Map.VisibleRegion
)仍处于打开状态。应该有一种方法可以绑定它们。为什么不在单个读/写属性中同时绑定这两个参数?(答案:因为出现了无限循环。)注意:如果您在启动时只需要一次
Map.MoveToRegion
,则可以在构造函数中设置该区域。wrrgggsh5#
我不认为
Pins
是Map
上的一个可绑定属性,您可能希望在Xamarin的Uservoice或此处的fourm上提交特性请求:http://forums.xamarin.com/discussion/31273/dgsult0t6#
这并不理想,但是你可以监听代码中的属性更改事件,然后从那里应用更改。这有点手动,但是是可行的。
然后定义“yourPropertyChanged”方法