Show map from VM

134 views Asked by At

I try to show on a ContentPage an ObservableCollection of type Activity (class I created). This one contains a Title (string) and a Map (xamarin.forms.maps) :

Map myMap = new Map();
myMap.IsShowingUser = true;
activity.Map = myMap;
obActivities.Add(activity);

Here is my XAML :

<ListView x:Name="listActivities" HorizontalOptions="StartAndExpand" VerticalOptions="FillAndExpand"
        SeparatorColor="LightGray" SeparatorVisibility="Default" HasUnevenRows="True"
        ItemsSource="{Binding obActivities}" CachingStrategy="RecycleElement"
        ItemSelected="ListActivities_ItemSelected" SelectedItem="{Binding selectedActivity,Mode=TwoWay}" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal" Padding="5" VerticalOptions="FillAndExpand">

                            <ContentView Content="{Binding Map}"></ContentView>
                            <Label Text="{Binding Title}" FontSize="12" TextColor="Gray"/>
                            
                            
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

The Title is well displayed.

I tried a lot of things (may be everything I can ^^) to show the Map but nothing works. The last thing I tried before this post... <ContentView Content="{Binding Map}"></ContentView> but no result.

EDIT : I also tried to add my map control onto the XAML like :

<map:Map>
   <map:Map.MapElements>
     <map:Polyline>
        <map:Polyline.Geopath>
                                                
        </map:Polyline.Geopath>
     </map:Polyline>
   </map:Map.MapElements>
</map:Map>

But I don't know where I have to add the polyline's position from my VM. May be you can help me to find the right XAML ...

1

There are 1 answers

0
ToolmakerSteve On
  1. I recommend managing a collection of UI elements (here, Maps) from inside the View or Page. I would move all the ViewModel code into the Page's code behind .xaml.cs file. There is still a "model" for each item ("Activity"), but no longer a ViewModel corresponding to the Page itself.

NOTE: This is an "impure" approach, as Activity is a mixture of model and UI information. Nevertheless, it is simpler code to do it this way. So I won't attempt to show a "pure" solution. In a simple case, the complications of doing so outweigh the "maintenance" benefit [easier to make changes without causing a bug] of keeping view and model separate. If this causes some problem later, refactor at that time.

Then BindingContext becomes the page itself:

public MyPage() {
    InitializeComponent();
    InitMyData();
    BindingContext = this;
}

public ObservableCollection<Activity> obActivities { get; set; } = new ObservableCollection<Activity>();

void InitMyData() {
    Map myMap = new Map();
    myMap.IsShowingUser = true;
    activity.Map = myMap;
    obActivities.Add(activity);
}

  1. The Map may lack a height when it is created. StackLayout may have given it "0" height by default. Specify some height:

     Map myMap = new Map();
     myApp.HeightRequest = 100;
    

Having a "hardcoded" height (e.g. 100) also helps speed up the initial layout of the page.