在 MVVM 中向 Xamarin.Maps 添加多个 Pin 图
Posted
技术标签:
【中文标题】在 MVVM 中向 Xamarin.Maps 添加多个 Pin 图【英文标题】:Add multiple Pins to Xamarin.Maps in MVVM 【发布时间】:2019-02-04 16:14:34 【问题描述】:我在尝试了解如何将 Pins 添加到 MVVM 模式中的地图时遇到问题。 (我可以在视图中有多个地图)。
这是我的 ViewModel 代码。
<flv:FlowListView SeparatorVisibility="Default" HasUnevenRows="True" FlowItemTappedCommand="Binding ItemTappedCommand" FlowLastTappedItem="Binding LastTappedItem" FlowColumnMinWidth="600" FlowItemsSource="Binding DashboardWidgets" >
<flv:FlowListView.FlowColumnTemplate>
<StackLayout BackgroundColor="White" Margin="1">
<!--Map Widgets -->
<StackLayout BackgroundColor="Binding bgcolor" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" IsVisible="False" >
<StackLayout.Triggers>
<DataTrigger TargetType="StackLayout" Binding="Binding resultsettype" Value="map">
<Setter Property="IsVisible" Value="True"/>
</DataTrigger>
</StackLayout.Triggers>
<StackLayout Orientation="Vertical" Padding="4" HeightRequest="400" WidthRequest="600">
<maps:Map x:Name="MyMap" IsShowingUser="true" MapType="Hybrid" />
</StackLayout>
</StackLayout>
<!--Image Widgets -->
<StackLayout BackgroundColor="Binding bgcolor" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" HeightRequest="200" WidthRequest="600" Padding="4" IsVisible="False">
<StackLayout.Triggers>
<DataTrigger TargetType="StackLayout" Binding="Binding resultsettype" Value="image">
<Setter Property="IsVisible" Value="True"/>
</DataTrigger>
</StackLayout.Triggers>
<StackLayout Padding="1" HeightRequest="200" WidthRequest="600">
<Image Source="Binding contentvalue, Converter=StaticResource LocalBase64ToImageConverter" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</StackLayout>
</StackLayout>
</flv:FlowListView.FlowColumnTemplate>
我有一个可观察的 DashboardWidgets 集合,它可以保存地图、图像、整数或列表。 如果是地图,我将获取 VM 中的所有引脚并以某种方式将它们绑定到地图。由于我使用的是 mvvm 模式,因此我不应该在我的 VM 中访问 Map,而且我也不知道该怎么做。
到目前为止,我已经尝试过扩展地图以使引脚可绑定,但没有成功。
public class ExtendedMap : Map
public static readonly BindableProperty PinsProperty = BindableProperty.Create(nameof(MultiPins), typeof(IList<Pin>), typeof(ExtendedMap), new List<Pin>());
public List<Pin> MultiPins
get
var val = (List<Pin>)GetValue(PinsProperty);
return new List<Pin>();
set => SetValue(PinsProperty, value);
我尝试创建一个内容视图,将其内容绑定到 vm 内的属性,但没有成功。
XAML: 两个都试过了。没有任何效果。
<contentview content=binding widgetResult />
<contentview content=binding mapresult />
虚拟机: VM 实现 IPropertyChanged。
var map = new Map(MapSpan.FromCenterAndRadius(new Position(37, -122), Distance.FromMiles(0.3)))
IsShowingUser = true,
HeightRequest = 100,
WidthRequest = 960,
VerticalOptions = LayoutOptions.FillAndExpand
;
(await GetMapPins(widget.filter)).ForEach(f => map.Pins.Add(f));
widget.widgetResult = new ContentView
Content = map
;
widget.mapresult = map;
【问题讨论】:
MVVM 并不一定意味着使用绑定做所有事情。您可以在代码中进行视图工作,这就是为什么每个视图都有一个 C# 代码隐藏文件。因此,您可以将地图和引脚的数据保留在 View Model 中,然后通过 View 的 C# 代码,您可以从 ViewModel 中获取 Map/Pin 数据,并在代码中根据需要将地图/引脚添加到 UI。这不违反 MVVM 模式 IMO。有些事情在代码中比设置复杂的绑定更容易做和理解。 @jgoldberger-MSFT 我同意你的看法。我尝试在视图中设置内容视图并从视图模型中添加内容。我可能做错了什么,只是没有用。 【参考方案1】:这是错误的:
public static readonly BindableProperty PinsProperty = BindableProperty.Create(nameof(MultiPins), typeof(IList<Pin>), typeof(ExtendedMap), new List<Pin>());
public List<Pin> MultiPins ...
BindableProperty 的名称必须是属性本身的名称,在本例中为“MultiPins”加上“Property”,因此 BindableProperty 名称必须是“MultiPinsProperty”,例如:
public static readonly BindableProperty MultiPinsProperty = BindableProperty.Create(nameof(MultiPins), typeof(IList<Pin>), typeof(ExtendedMap), new List<Pin>());
public List<Pin> MultiPins ...
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/bindable-properties#creating-a-property
可绑定属性的命名约定是可绑定属性标识符必须与 Create 方法中指定的属性名称匹配,并附加“Property”。
【讨论】:
以上是关于在 MVVM 中向 Xamarin.Maps 添加多个 Pin 图的主要内容,如果未能解决你的问题,请参考以下文章