Xamarin Forms: How to bind the position value of Xamarin.forms.Maps inside the ListView?

Sreejith Sree 1,251 Reputation points
2020-12-21T10:25:58.207+00:00

I am using Xamarin.forms.Maps for showing the map in my project. The map is inside the listview and I need to bind the coordinate positions to the map.

My code:

Model Class:

public class History  
{  
	public double Latitude { get; set; }  
	public double Longitude { get; set; }  
}  

Data adding part:

historyList.Add(new History() { Latitude= -28.854930 ,Longitude= 151.166023 });   
historyList.Add(new History() { Latitude = -28.853671, Longitude = 151.165712 });   
historyList.Add(new History() { Latitude = -28.853934, Longitude = 151.167118 });   
historyList.Add(new History() { Latitude = -28.855178, Longitude = 151.167946 });   
historylistview.ItemsSource = historyList;  

XAML

<ListView x:Name="historylistview">  
	<ListView.ItemTemplate>  
		<DataTemplate>  
			<ViewCell>  
				<ViewCell.View>  
						<StackLayout  
							 HorizontalOptions="Center">  
							<maps:Map   
								x:Name="maps"   
								VerticalOptions="Center"   
								HorizontalOptions="Center">  
								<x:Arguments>  
									<maps:MapSpan>  
										<x:Arguments>  
											<maps:Position>  
												<x:Arguments>  
													<x:Double>{Binding Latitude}</x:Double>  
													<x:Double>{Binding Longitude}</x:Double>  
												</x:Arguments>  
											</maps:Position>  
											<x:Double>0.01</x:Double>  
											<x:Double>0.01</x:Double>  
										</x:Arguments>  
									</maps:MapSpan>  
								</x:Arguments>  
							</maps:Map>  
						</StackLayout>  
				</ViewCell.View>  
			</ViewCell>  
		</DataTemplate>  
	</ListView.ItemTemplate>  
</ListView>   

The map is showing in each row but the position value are wrong. I have given location from Texas but the map is showing somewhere in Nijerya.

49908-processed.jpeg

Is binding is possible to do for the type x:Arguments?

Developer technologies | .NET | Xamarin
0 comments No comments
{count} votes

Accepted answer
  1. Anonymous
    2020-12-21T11:24:36.793+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    MapSpan and Position in Map are not bindable property , so it will never work if you use data binding .

    If you want to display a list of positions

       <Grid>  
               ...  
               <maps:Map x:Name="map"  
                         ItemsSource="{Binding historyList}">  
                   <maps:Map.ItemTemplate>  
                       <DataTemplate>  
                           <maps:Pin Position="{Binding Position}"/>  
                       </DataTemplate>  
                   </maps:Map.ItemTemplate>  
               </maps:Map>  
               ...  
           </Grid>  
    
    
       historyList.Add(new History() { Position = new Position(36.9628066, -122.0194722)});  
       historyList.Add(new History() { Position = new Position(36.9628066, -122.0194722) });  
       //...  
       historylistview.ItemsSource = historyList;  
    
    
    
       public class History  
       {  
           public Position Position { get; set; }       
       }  
    

    You can check lucas's reply:

    https://stackoverflow.com/questions/65390620/xamarin-forms-how-to-bind-the-position-value-of-xamarin-forms-maps-inside-the-l

    ===========
    Update================

    You can create an custom view.

       <ContentView xmlns="http://xamarin.com/schemas/2014/forms"   
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"   
                    xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"  
                    x:Name="this"  
                    x:Class="MapDemo.MyMapView">  
         <ContentView.Content>  
             <StackLayout>  
                   <maps:Map    
                                           x:Name="maps"   
                                           MoveToLastRegionOnLayoutChange="True"  
                                           VerticalOptions="Start"   
                                           HorizontalOptions="End"  
                                           HasScrollEnabled="false"  
                                           
                                           ItemsSource="{Binding Source={x:Reference this}, Path=MapPostions}"  
                                           Margin="0,10,10,0">  
                       <maps:Map.ItemTemplate>  
                           <DataTemplate>  
                               <maps:Pin   
                                   Position="{Binding Position}"  
                                   Label=""/>  
                           </DataTemplate>  
                       </maps:Map.ItemTemplate>  
                       <maps:Map.HeightRequest>  
                           <OnIdiom x:TypeArguments="x:Double" Phone="100" Tablet="200" Desktop="100"/>  
                       </maps:Map.HeightRequest>  
                       <maps:Map.WidthRequest>  
                           <OnIdiom x:TypeArguments="x:Double" Phone="150" Tablet="220" Desktop="150"/>  
                       </maps:Map.WidthRequest>  
                   </maps:Map>  
               </StackLayout>  
         </ContentView.Content>  
       </ContentView>  
         
         
         [XamlCompilation(XamlCompilationOptions.Compile)]  
           public partial class MyMapView : ContentView  
           {  
               public MyMapView()  
               {  
                   InitializeComponent();  
               }  
         
               public static readonly BindableProperty MapPostionsProperty = BindableProperty.Create("MapPostions", typeof(ObservableCollection<History>), typeof(MyMapView), null);  
         
               public ObservableCollection<Position> MapPostions  
               {  
                   get { return (ObservableCollection<Position>)GetValue(MapPostionsProperty); }  
                   set { SetValue(MapPostionsProperty, value); }  
               }  
         
         
               public static readonly BindableProperty MapMovePositionProperty = BindableProperty.Create("MapMovePosition", typeof(Position), typeof(MyMapView), null, propertyChanged: MapMoveChangeValue);  
         
               public Position MapMovePosition  
               {  
                   get { return (Position)GetValue(MapMovePositionProperty); }  
                   set { SetValue(MapMovePositionProperty, value); }  
               }  
               private static void MapMoveChangeValue(BindableObject bindable, object oldValue, object newValue)  
               {  
         
                   MyMapView view = bindable as MyMapView;  
         
                   if (view!=null)  
                   {  
                       Position position = (Position)newValue;  
                       view.maps.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromMiles(1)));  
                   }  
                    
               }  
           }  
       }  
    

    Then, you can use it in your listview. And do not forget to set CachingStrategy="RecycleElement" for your listview.

       <ListView   
                   x:Name="historylistview"  
                   SeparatorVisibility="None"  
                   HasUnevenRows="True"  
                 CachingStrategy="RecycleElement"  
                   BackgroundColor="#ffffff">  
                   <ListView.ItemTemplate>  
                       <DataTemplate>  
                           <ViewCell>  
                               <ViewCell.View>  
                                   <StackLayout  
                                       Orientation="Horizontal"  
                                       VerticalOptions="CenterAndExpand">  
         
                                       <Label   
                                           Text="{Binding name}"  
                                           HorizontalOptions="Start"  
                                           VerticalOptions="CenterAndExpand"  
                                           TextColor="#545454">  
                                           <Label.FontSize>  
                                               <OnIdiom x:TypeArguments="x:Double">  
                                                   <OnIdiom.Phone>15</OnIdiom.Phone>  
                                                   <OnIdiom.Tablet>22</OnIdiom.Tablet>  
                                                   <OnIdiom.Desktop>15</OnIdiom.Desktop>  
                                               </OnIdiom>  
                                           </Label.FontSize>  
                                       </Label>  
                                       <mapdemo:MyMapView  
                                            MapPostions="{Binding positionList}"  
                                           MapMovePosition="{Binding MovePosition}"  
                                           ></mapdemo:MyMapView>  
                                       
                                   </StackLayout>  
                               </ViewCell.View>  
                           </ViewCell>  
                       </DataTemplate>  
                   </ListView.ItemTemplate>  
               </ListView>  
    

    In the listview background code. add public Position MovePosition { get; set; } to your History class.

       public void SetMapItems()  
               {  
                   historyList.Add(new History() { name = "map1",MovePosition= new Position(30.002767, -96.365928), positionList = new ObservableCollection<Position>() { new Position(30.002767, -96.365928) } });  
                   historyList.Add(new History() { name = "map2", MovePosition = new Position(29.308168, -98.450792), positionList = new ObservableCollection<Position>() { new Position(29.308168, -98.450792) } });  
                   historyList.Add(new History() { name = "map3", MovePosition = new Position(35.727875, 139.202426), positionList = new ObservableCollection<Position>() { new Position(35.727875, 139.202426) } });  
                   historyList.Add(new History() { name = "map4", MovePosition = new Position(35.764271, 139.188613), positionList = new ObservableCollection<Position>() { new Position(35.764271, 139.188613) } });  
                   historyList.Add(new History() { name = "map5", MovePosition = new Position(52.490629, 13.442549), positionList = new ObservableCollection<Position>() { new Position(52.490629, 13.442549) } });  
                   historyList.Add(new History() { name = "map6", MovePosition = new Position(52.501651, 13.428040), positionList = new ObservableCollection<Position>() { new Position(52.501651, 13.428040) } });  
                   historyList.Add(new History() { name = "map7", MovePosition = new Position(-1.299773, 36.856996), positionList = new ObservableCollection<Position>() { new Position(-1.299773, 36.856996) } });  
                   historyList.Add(new History() { name = "map8", MovePosition = new Position(-1.299773, 36.856996), positionList = new ObservableCollection<Position>() { new Position(-1.293129, 36.858975) } });  
                   historylistview.ItemsSource = historyList;  
               }  
           }  
         
           public class History  
           {  
               public string name { get; set; }  
         
               
               public Position MovePosition { get; set; }  
         
               public ObservableCollection<Position> positionList { get; set; }  
           }  
    

    Best Regards,

    Leon Lu


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.