在 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 图的主要内容,如果未能解决你的问题,请参考以下文章

在 VUE 中向 href 添加数据

在 Fragment 中向 ActionBar 添加项目

在自动布局中向 UILabel 添加填充

如何在 UITabBarController 中向 UINavigationController 添加右键?

在 iPhone 中向 UIImage 添加类别

在 Android 中向地图添加标记