【问题标题】:Maps in Xamarin Forms and MVVM architectureXamarin 表单和 MVVM 架构中的映射
【发布时间】:2017-09-01 13:40:16
【问题描述】:

如何在 Xamarin Forms 和 MVVM 架构中显示地图。如何在 ModelView 中的地图上创建位置并在 PageView 中显示?

查看

<?xml version="1.0" encoding="UTF-8"?>
<d:ExtendedContentPage xmlns:d="clr-namespace:TestApp;assembly=TestApp"
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="TestApp.MapPageView">
    <ContentPage.Content>
 <StackLayout VerticalOptions="StartAndExpand" Padding="30">
        <maps:Map WidthRequest="320" HeightRequest="200"
            Text="{Binding MapModel.MyMap]"
            IsShowingUser="true"
            MapType="Hybrid"/>
  </StackLayout>
 </ContentPage.Content>
</d:ExtendedContentPage>

模型视图

public class MapViewModel: BaseViewModel
{
    private MapModel _mapModel = null;
    private MapModel MapModel
    {
        get
        {
            return _mapModel;
        }
        set
        {
            if (_mapModel != value)
            {
                _mapModel = value;
                OnPropertyChanged();
            }
        }
    }

    public MapViewModel(INavigation navigation) : base(navigation)
    {
        InitializeMapsPosition();
    }

    private  void InitializeMapsPosition()
    {

    }

    public override void RemoveHandlers()
    {
        throw new NotImplementedException();
    }
}

型号

public class MapModel
{
    public string MyMap { set; get; }

    public MapModel(String myMap) 
    {
        MyMap = myMap;
    }
}

【问题讨论】:

    标签: c# xamarin mvvm


    【解决方案1】:

    在我的场景中,我需要在地图中显示一些地方的位置和当前位置。 我使用 Xamarin.Forms.Maps 来显示地图 对于地图中的位置:我添加了一个 CustomMap 类并编写了两个属性注入来显示地图中的图钉。一个属性 (CenterRegion) 用于显示当前位置,另一个属性 (CustomPins) 用于显示地图中的地点位置。

    自定义地图类

      public class CustomMap : Map
    {
        private static IList<Pin> AllPins;
    
        public Location CenterRegion
        {
            get { return (Location)GetValue(CenterRegionProperty); }
            set { SetValue(CenterRegionProperty, value); }
        }
    
    
        public static readonly BindableProperty CenterRegionProperty =
           BindableProperty.Create(propertyName: nameof(CenterRegion), returnType: 
           typeof(Location), declaringType: typeof(CustomMap), defaultValue: null, 
           propertyChanged: (sender, oldValue, newValue) =>
           {
               CustomMap map = (CustomMap)sender;
    
               if (newValue is Location location)
               {
                   map.MoveToRegion(MapSpan.FromCenterAndRadius(new 
                   Position(location.Latitude, location.Longitude), 
                   Distance.FromMiles(3)));
               }
           });
    
    
        public IEnumerable CustomPins
        {
            get { return (IEnumerable)GetValue(CustomPinsProperty); }
            set { SetValue(CustomPinsProperty, value); }
        }
    
        public static readonly BindableProperty CustomPinsProperty =
            BindableProperty.Create(propertyName: nameof(CustomPins), returnType: 
            typeof(IEnumerable), declaringType: typeof(CustomMap), defaultValue: null, 
            propertyChanged: (sender, oldValue, newValue) =>
            {
                CustomMap map = (CustomMap)sender;
    
                AllPins = new List<Pin>();
    
                map.Pins.Clear();
    
                if (newValue is IEnumerable spaces)
                {
                    foreach (Pin pin in ConvertSpacesToPins(spaces))
                           map.Pins.Add(pin);
                }
                AllPins = map.Pins;
                map.OnPropertyChanged("Pins");
            });
    
    
        public static List<Pin> ConvertSpacesToPins(IEnumerable spaces)
        {
            if (spaces == null)
                return null;
    
            List<Pin> result = new List<Pin>();
    
            foreach (SpaceDto space in spaces.OfType<SpaceDto>())
            {
                double latitude = space.Latitude;
                double longitude = space.Longitude;
                string spaceTitle = space.Title;
                Position position = new Position(latitude, longitude);
    
                Pin pin = new Pin
                {
                    Position = position,
                    Label = spaceTitle
                };
                    result.Add(pin);
            }
            return result;
        }
    }
    

    Xaml 页面

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:Map="clr-namespace:XamarinFormsPrismMapSample.Views"
                     x:Class="XamarinFormsPrismMapSample.Views.CustomMapSampleView">
            <Map:CustomMap
                        CenterRegion="{Binding CurrentLocation}"
                        CustomPins="{Binding Spaces}"
                        HorizontalOptions="FillAndExpand"
                        IsShowingUser="true"
                        MapType="Street"
                        VerticalOptions="FillAndExpand" />
        </ContentPage>
    

    视图模型:

    public class CustomMapSampleViewModel : BindableBase
        {
            public Location CurrentLocation { get; set; }
            public SpaceDto Spaces { get; set; }
    
            public CustomMapSampleViewModel()
            {
    
            }
    
            public async Task OnNavigatedToAsync(NavigationParameters parameters)
            {
                Location CurrentLocation = await Geolocation.GetLastKnownLocationAsync();
                List<SpaceDto> Spaces = new List<SpaceDto> { 
                new SpaceDto { Latitude = 45.6892 , Longitude = 51.3890, Title = "X"  }, 
                new SpaceDto { Latitude = 45.6891, Longitude = 51.3890, Title = "Y" }, 
                new SpaceDto { Latitude = 45.6888, Longitude = 51.3890, Title = "Z" } };
            }
        }
    
        public class SpaceDto
        {
            public string Title { get; set; }
            public virtual double Latitude { get; set; }
            public virtual double Longitude { get; set; }
        }
    

    【讨论】:

      【解决方案2】:

      是的,Map.Pins 是不可绑定的,但是有ItemsSource,而是easy to use

         <maps:Map ItemsSource="{Binding Locations}">
              <maps:Map.ItemTemplate>
                  <DataTemplate>
                      <maps:Pin Position="{Binding Position}"
                                Label="{Binding Name}"
                                Address="{Binding Subtitle}" />
      

      因此,仅对于引脚,MVVM 可以在没有任何自定义控件的情况下完成。 但是Map.MoveToRegion()(和Map.VisibleRegion 阅读)仍然开放。应该有办法绑定它们。为什么不在一个读/写属性中? (答案:因为无限循环。)

      注意:如果Map.MoveToRegion在启动时只需要一次,可以在构造函数中设置区域。

      【讨论】:

        猜你喜欢
        • 2020-07-22
        • 1970-01-01
        • 2021-08-12
        • 2015-05-21
        • 1970-01-01
        • 2021-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多