ThinkGeo.com    |     Documentation    |     Premium Support

Migrating from v13 to v14

Hi,

I am trying to migrate ThinkGEO XamarinForms to MAUI, it seems the implementation has changed.
Not sure what to do to make the previous code work…

  1. Setting Current Extent
    In v13, we could set the CurrentExtent as below.
    mapView.CurrentExtent = myCustomExtent;
    In v14, CurrentExtent setter seem to be hided. How could I set it in v14?

  2. Touch/Tap event
    In v13, we have below event handlers and the args is TouchMapViewEventArgs

    mapView.MapSingleTap -= mapView_MapClick;
    mapView.MapSingleTap += mapView_MapClick;

    mapView.MapDoubleTap -= mapView_MapDoubleClick;
    mapView.MapDoubleTap += mapView_MapDoubleClick;

But in v14, I think they have changed to
mapView.SingleTap -= mapView_MapClick;
mapView.SingleTap += mapView_MapClick;

mapView.DoubleTap -= mapView_MapDoubleClick;
mapView.DoubleTap += mapView_MapDoubleClick;

However, the eventArgs SingleTapMapViewEventArgs,DoubleTapMapViewEventArgs does not have property, PointInWorldCoordinate anymore. How to retrieve this property in v14?

  1. ZoomMapTool
    In v13, we could hide the zoomMapTool by
    mapView.MapTools.ZoomMapTool.IsEnabled = false;

But in v14, mapView.MapTools.ZoomMapTool is no longer exist, how could I disable the zoomMapTool?

  1. ZoomLevelSet
    In v13, we could do
    var defaultMapScale = mapView.ZoomLevelSet.ZoomLevel12.Scale;
    but in v14, ZoomLevelSet is no longer exist, how could I do the same thing?

Thank you

Hi Jimmy,

  1. In Maui, we use MapView.CenterPoint and MapView.MapScale for the extent, it’s better than CurrentExtent especially when RotationAngle is not 0.

  2. You can use the following line to convert screen coordinates to world coordinates:
    var pointInWorldCoordinate = MapView.ToWorldCoordinate(e.X, e.Y);

In fact let me write it down and we will discuss about it and may add PointInWorldCoordiante back.

  1. in Maui, you can add ZoomMapTool in xaml like following:

         <thinkgeo:MapView Grid.Row="1" x:Name="MapView" Grid.RowSpan="2" 
                           MapRotation="0" SizeChanged="MapView_OnSizeChanged">
             <thinkgeo:MapView.MapTools>
                 <thinkgeo:ZoomMapTool />
             </thinkgeo:MapView.MapTools>
         </thinkgeo:MapView>
    

ZoomMapTool is a standalone Maui component, you can just set IsVisible to show/hide it.

  1. In Maui, zoomLevelSet on MapView is a bit confusing because you can stop the map at any scale, that’s why we removed it. Now we have TileOverlay.ZoomLevelSet, which identifies the zoomlevels of the tiles, is this something you can use? Let me know your scenario and we can give you a better suggestion.

Please play with the Maui HowDoI samples : ThinkGeo / Public / Mobile Maps · GitLab, where you can find lots of good sample codes.

Thanks,
Ben

Thank you Ben.
Just got another question.
I am using XyzTileAsyncLayer in Xamarin app, but somehow in MAUI, the layer is not showing.

After some testing, it seems that Insert function is not working and have to use “Add” otherwise the map is not showing up. Am I missing something or it has a bug?

MapView.Overlays.Insert(0, layerOverlay);

Please find the attached sample.Xyz.xaml (683 Bytes) Xyz.xaml.cs (2.3 KB)

Another issue is the map is sometime not loading…It is loaded after moving the extent, but it will then behavior strange (cannot drag to move etc)
I can see the log as below

java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
[Glide] at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:363)
[Glide] at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:239)
[Glide] at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1853)
[Glide] at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1773)
[Glide] at com.bumptech.glide.load.data.AssetFileDescriptorLocalUriFetcher.loadResource(AssetFileDescriptorLocalUriFetcher.java:20)
[Glide] at com.bumptech.glide.load.data.AssetFileDescriptorLocalUriFetcher.loadResource(AssetFileDescriptorLocalUriFetcher.java:11)
[Glide] at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:44)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:416)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:223)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:108)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.startNextOrFail(MultiModelLoader.java:167)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.onLoadFailed(MultiModelLoader.java:154)
[Glide] at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:50)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:416)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:223)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:108)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.startNextOrFail(MultiModelLoader.java:167)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.onLoadFailed(MultiModelLoader.java:154)
[Glide] at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:50)
[Glide] at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95)
[Glide] at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:280)
[Glide] at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235)
[Glide] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
[Glide] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
[Glide] at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:424)
[Glide] at java.lang.Thread.run(Thread.java:1012)
[Glide] at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultPriorityThreadFactory$1.run(GlideExecutor.java:383)

I am using v14.2.1 with Android, not tested with iOS so far.

Thank you

Hi Jimmy,

Thanks for letting us know!

  1. It is a bug that Overlays.Insert doesn’t work. The bug is fixed in 14.3.0-beta071 and later versions, please pull the latest and have another try. (The fix is not included in the latest release v14.2.2)
  2. I couldn’t recreate the map-is-sometime-not-loading-issue, can you pull the latest version and have another try? Here are some settings you can play with:
  • change the overlay.TileType to TileType.MultiTile (it’s singleTile by default), change the tileSize to 256 or 512(default)
  • Show the tile ID on the tiles: ThinkGeoDebugger.DisplayTileId = true;
  • Show more debug info in the Output window:
    ThinkGeoDebugger.LogLevel = ThinkGeoLogLevel.All;
    ThinkGeoDebugger.LogType = ThinkGeoLogType.Rendering;

Please let us know the model or your device/emulation if you still see issue #2.

Thanks,
Ben

Thanks Ben,

It seems issue 2 is not happening in the latest beta version so far…
will keep an eye to see if it happens again.

By the way, may I know if there is any build in clustering feature in the library?
Thank you

Yes, and we have a cluster sample in HowDoI -> Vector Data Styling -> Display Cluster Points

1 Like

Hi Ben,

I am working on the clustering and hope that I could get some ideas on the refresh map.
Currently my map view has 3 overlay

  1. Base overlay where store the map
  2. Marker overlay where store all the marker
  3. Drawing overlay where store all drawing from user

In Marker overlay, there are 3 layer

  1. For all PointStyle feature, that include cluster point
  2. For all AreaStyle feature
  3. For all LineStyle feature

I am now hitting Collection was modified error, probably causing by frequently updating the map.
My question is when should I update the map to reload the features? It has to reload since the cluster points will contains different numbers of children in different zoom level.

Below are the captured log when the error happens

[0:] ThinkGeo Message - 15:19:30.3868405: TileOverlay Draw Start
[0:] ThinkGeo Message - 15:19:30.4134965: TileView 68: 0-0-0 Draw Start
[0:] ThinkGeo Message - 15:19:30.4581910: Animation Start
[0:] ThinkGeo Message - 15:19:30.4966393: Tile 68: 0-0-0 SetImageAsync Start
[0:] ThinkGeo Message - 15:19:30.6082029: TileView 68: 0-0-0 Drawn End
[0:] ThinkGeo Message - 15:19:30.6407391: Single Tile Post Start
[0:] ThinkGeo Message - 15:19:30.6651089: TileView 68: 0-0-0 Post Start
[0:] ThinkGeo Message - 15:19:30.6936471: TileView 68: 0-0-0 Post End
[0:] ThinkGeo Message - 15:19:30.7262708: Animation Completed
[0:] ThinkGeo Message - 15:19:30.7750715: Draw Start
[0:] ThinkGeo Message - 15:19:30.8166265: TileOverlay Draw Start
[0:] ThinkGeo Message - 15:19:30.8305522: TileView 69: 0-0-0 Draw Start
[0:] ThinkGeo Message - 15:19:30.8879045: TileView 69: 0-0-0 Draw Canceled
[0:] ThinkGeo Message - 15:19:30.9180396: TileOverlay Draw Canceled
[0:] ThinkGeo Message - 15:19:30.9458411: Single Tile Post End
[0:] ThinkGeo Message - 15:19:30.9684162: TileOverlay Draw End
[0:] ThinkGeo Message - 15:19:30.9859835: TileOverlay Draw Start
[0:] ThinkGeo Message - 15:19:31.0044164: TileView 70: 0-0-0 Draw Start
[0:] ThinkGeo Message - 15:19:31.0333529: Draw Start
[0:] ThinkGeo Message - 15:19:31.0555145: TileOverlay Draw Start
[0:] ThinkGeo Message - 15:19:31.0779877: TileView 71: 0-0-0 Draw Start
[0:] ThinkGeo Message - 15:19:31.1486210: Tile 70: 0-0-0 SetImageAsync Start
[EGL_emulation] app_time_stats: avg=4.50ms min=1.23ms max=13.08ms count=31
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'v

[0:] ThinkGeo Message - 11:21:59.4341655: Animation Start
[tarn.android] Explicit concurrent mark compact GC freed 276KB AllocSpace bytes, 4(2256KB) LOS objects, 49% free, 13MB/27MB, paused 163us,2.797ms total 21.804ms
[0:] ThinkGeo Message - 11:21:59.6343927: Animation Completed
[0:] ThinkGeo Message - 11:21:59.6707048: Draw Start
[0:] ThinkGeo Message - 11:21:59.7026321: TileOverlay Draw Start
[0:] ThinkGeo Message - 11:21:59.7350229: TileView 18: 0-0-0 Draw Start
[0:] ThinkGeo Message - 11:21:59.7768920: Tile 18: 0-0-0 SetImageAsync Start
[0:] ThinkGeo Message - 11:21:59.8581408: TileView 18: 0-0-0 Drawn End
[0:] ThinkGeo Message - 11:21:59.8903703: Single Tile Post Start
[0:] ThinkGeo Message - 11:21:59.9270476: TileView 18: 0-0-0 Post Start
[0:] ThinkGeo Message - 11:21:59.9631924: TileView 18: 0-0-0 Post End
[0:] ThinkGeo Message - 11:22:00.0223977: Single Tile Post End
[EGL_emulation] app_time_stats: avg=17.23ms min=13.05ms max=36.00ms count=59
[0:] ThinkGeo Message - 11:22:00.0634218: TileOverlay Draw End
[0:] ThinkGeo Message - 11:22:00.1056683: TileOverlay Draw Start
[0:] ThinkGeo Message - 11:22:00.1454603: TileView 19: 0-0-0 Draw Start
[0:] ThinkGeo Message - 11:22:00.1851550: Tile 19: 0-0-0 SetImageAsync Start
[0:] ThinkGeo Message - 11:22:00.2817092: TileView 19: 0-0-0 Drawn End
[0:] ThinkGeo Message - 11:22:00.3260326: Single Tile Post Start
[0:] ThinkGeo Message - 11:22:00.3655159: TileView 19: 0-0-0 Post Start
[0:] ThinkGeo Message - 11:22:00.4077970: TileView 19: 0-0-0 Post End
[0:] ThinkGeo Message - 11:22:00.4686346: Single Tile Post End
[0:] ThinkGeo Message - 11:22:00.5169648: TileOverlay Draw End
[0:] ThinkGeo Message - 11:22:00.5593404: TileOverlay Draw Start
[0:] ThinkGeo Message - 11:22:00.6036609: TileView 20: 0-0-0 Draw Start
[0:] ThinkGeo Message - 11:22:00.9175623: Tile 20: 0-0-0 SetImageAsync Start
[EGL_emulation] app_time_stats: avg=16.97ms min=14.32ms max=36.59ms count=60
[0:] ThinkGeo Message - 11:22:01.0076016: TileView 16: 0-0-0 Post Timeout after 3000 ms
[0:] ThinkGeo Message - 11:22:01.1665241: Single Tile Post End
[0:] ThinkGeo Message - 11:22:01.2103720: TileOverlay Draw End
[0:] ThinkGeo Message - 11:22:01.2527594: TileOverlay Draw Start
[0:] ThinkGeo Message - 11:22:01.2912847: TileView 21: 0-0-0 Draw Start
[0:] ThinkGeo Message - 11:22:01.5792794: Tile 21: 0-0-0 SetImageAsync Start
[tarn.android] Explicit concurrent mark compact GC freed 816KB AllocSpace bytes, 67(9612KB) LOS objects, 49% free, 12MB/25MB, paused 172us,3.155ms total 27.988ms
[tarn.android] Explicit concurrent mark compact GC freed 108KB AllocSpace bytes, 0(0B) LOS objects, 49% free, 12MB/25MB, paused 144us,3.505ms total 21.346ms
[0:] ThinkGeo Message - 11:22:01.7845062: TileView 20: 0-0-0 Drawn End
[0:] ThinkGeo Message - 11:22:01.8235510: Single Tile Post Start
[0:] ThinkGeo Message - 11:22:01.8619871: TileView 20: 0-0-0 Post Start
[0:] ThinkGeo Message - 11:22:01.9054937: TileView 20: 0-0-0 Post End
[0:] Current location result lat=-37.8084 Lon=144.973505
[0:] Adding current location to user location layer
[0:] ThinkGeo Message - 11:22:02.0503605: TileOverlay Draw Start
[EGL_emulation] app_time_stats: avg=16.63ms min=13.62ms max=18.73ms count=61
[0:] ThinkGeo Message - 11:22:02.1050265: TileView 22: 0-0-0 Draw Start
[0:] Current location result lat=-37.8084 Lon=144.973505
[0:] Adding current location to user location layer
[0:] 0d031cc2-fdab-428f-be12-24a0446ede3d complete
[0:] ThinkGeo Message - 11:22:02.3363356: Single Tile Post End
[0:] ThinkGeo Message - 11:22:02.3759755: TileOverlay Draw End
[0:] ThinkGeo Message - 11:22:02.4226263: Draw End
[Choreographer] Skipped 35 frames! The application may be doing too much work on its main thread.
[tarn.android] Explicit concurrent mark compact GC freed 284KB AllocSpace bytes, 0(0B) LOS objects, 49% free, 12MB/25MB, paused 205us,5.089ms total 23.284ms
[0:] ThinkGeo Message - 11:22:02.5003530: TileView 21: 0-0-0 Drawn End
[0:] ThinkGeo Message - 11:22:02.5709452: Single Tile Post Start
[0:] ThinkGeo Message - 11:22:02.6107090: TileView 21: 0-0-0 Post Start
[0:] ThinkGeo Message - 11:22:02.6509705: TileView 21: 0-0-0 Post End
[tarn.android] Explicit concurrent mark compact GC freed 128KB AllocSpace bytes, 0(0B) LOS objects, 49% free, 12MB/25MB, paused 188us,2.653ms total 19.626ms
System.InvalidOperationException: ‘Collection was modified; enumeration operation may not execute.’

Hi Jimmy,

It shouldn’t throw a ‘Collection was modified’ exception; it must be a bug.

Thanks for the log, but sorry I cannot determine the cause. Could you please send a demo project to us or share some code showing how you update the map? (You can either email it or create a ticket and upload it there if you prefer not to disclose it publicly). I’m wondering how you were updating the map, maybe keep updating the marker positions?

Thanks,
Ben

Hi Jimmy,

Yes, the ThinkGeo library does use Microsoft.Data.Sqlite (which includes SQLitePCLRaw.bundle_e_sqlite3) in MAUI versions as well, you can decouple SQLitePCLRaw.bundle_e_sqlite3 and replace it with SQLitePCLRaw.bundle_e_sqlcipher just like you did in Xamarin.Forms.

Thanks,
Ben

Hi Jimmy,

Yes, the ThinkGeo library does use Microsoft.Data.Sqlite (which includes SQLitePCLRaw.bundle_e_sqlite3) by default in MAUI as well, and you can decouple it and replace it with SQLitePCLRaw.bundle_e_sqlcipher just like you did in Xamarin.Forms.

Thanks,
Ben