Virtualization issue

10 posts, 0 answers
  1. Jason D
    Jason D avatar
    114 posts
    Member since:
    Jan 2011

    Posted 06 Mar 2018 Link to this post

    Having a very frustrating problem. My sample project works perfectly, but my real application does not. I implemented IMapItemsVirtualizationSource and everything shows up fine. When I change the zoom, MapItemsRequest is called. I verified that only the items for the corresponding zoomlevel are added to CompleteItemsRequest. However, the items from the previous zoom level are still shown on the map. If I pan the map so that the items are out of view and then pan back to the original location, the old items are gone. It appears that changing the zoom level is not causing the old items to be removed. Any ideas what could cause this? Version 2014.3.1202.45. This is the first time I've tried using virtualization.
  2. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3086 posts

    Posted 07 Mar 2018 Link to this post

    Hi Jason,

    First, let me make the note that RadMap does not decide which items are added on ZoomLevel X and which are removed on ZoomLevel Y. Map just throws the mentioned MapItemReqest event handler and you decide what to include. Items outside viewport will be cleared at certain moment. To better specify how the event is called on changing zoom levels, you need to define ZoomLevelGridLists:
    <telerik:VisualizationLayer x:Name="visualizationLayer"
                                   ItemTemplateSelector="{StaticResource StoreTemplateSelector}"
                                   VirtualizationSource="{StaticResource MyVirtualizationSource}">
                   <telerik:VisualizationLayer.ZoomLevelGridList>
                       <telerik:ZoomLevelGrid MinZoom="3" />
                       <telerik:ZoomLevelGrid MinZoom="9" />
                   </telerik:VisualizationLayer.ZoomLevelGridList>
               </telerik:VisualizationLayer>

    For example with the following setup, starting at zoom level 3, MapItemRequest will be fired for the regions in the ViewPort. If you zoom on single point with no panning, the event will be fired when you reach zoom level 9 and won't be fired for zoom levels  4 5 6 7 8.

    I hope this explanation could help you move forward in your scenario. On the other hand, I highly encourage you to upgrade to our latest official Release and check if the behavior you encountered is still reproducible.

    Regards,
    Petar Mladenov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  3. Jason D
    Jason D avatar
    114 posts
    Member since:
    Jan 2011

    Posted 07 Mar 2018 in reply to Petar Mladenov Link to this post

    Thanks. That's what I'm doing, it's just not working. When I zoom, old items are still there even though I did not add them to the current MapItemRequest. There must be some difference, I just can't find it. I will see if I can get approval to upgrade this week.
  4. Jason D
    Jason D avatar
    114 posts
    Member since:
    Jan 2011

    Posted 20 Mar 2018 Link to this post

    I did update to the latest version, but I'm still seeing the same issue. I haven't been able to find a difference between the two projects yet. I've even simplified the code. Will update if I can make a sample project or find the cause.
  5. Jason D
    Jason D avatar
    114 posts
    Member since:
    Jan 2011

    Posted 22 Mar 2018 Link to this post

    Petar,

    I found the problem, although I don't understand Telerik's code enough to know if this is a "bug" or if it's something in my app. All comments refer to the VisualizationLayer class.

    Good app: When I change the zoom, UpdateVirtualItemsForZoom is called first. matrixIndex != this.lastRequestedIndex so ClearItems is called and all is well.

    Bad app: When I change the zoom, UpdateThreadParameters is called first. lastRequestedIndex is updated to be matrixIndex. Then UpdateVirtualItemsForZoom is called. Now, matrixIndex = this.lastRequestedIndex, to ClearItems is not called and the layer contains the items from the previous zoom level.

    Both apps are WinForms and the map control is hosted. The Map control is contained in a WPF DLL.

  6. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3086 posts

    Posted 23 Mar 2018 Link to this post

    Hello Jason,

    This seems a threading issue since UpdateThreadParameters is called by background threads via Dispatcher in order to execute the method on the main UI thread. For us it is of high importance to reproduce such issue locally in order to log it and investigate it further. Is there any chance you can isolate the the 'bad app' further and send it here ? Also, since the root project is Winforms, we need to say we have RadMap in our Win Forms components too so you can give it a try.

    RadMap for Winforms Overview

    Regards,
    Petar Mladenov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  7. Jason D
    Jason D avatar
    114 posts
    Member since:
    Jan 2011

    Posted 23 Mar 2018 in reply to Petar Mladenov Link to this post

    Ok, I figured it out. When the zoom changes, I have to create a new tiled provider (unrelated to the visualization layer) because the data cannot be scaled and has to be redrawn each time. I need to know when the map finished rendering my new data, so I have this code:

    System.Windows.Application.Current.Dispatcher.Invoke(New Action(AddressOf MapDrawFinished), System.Windows.Threading.DispatcherPriority.ContextIdle)

    If I take that line out, everything works. If I change it BeginInvoke, it will also work. I'll see if I still need this or if using BeginInvoke is acceptable or if there is another alternative. Any ideas why this would cause problems?
  8. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3086 posts

    Posted 26 Mar 2018 Link to this post

    Hello Jason,

    I am not sure what this MapDrawfFinished action / event does because it is part of your application / custom component. I guess you call it in MapItemRequest which is fired by background threads and your BeginInvoke invocation throws the action to the UI (Main UI Thread) which performs UI operation (hide/ move) of UI Elements. Again, as I am not sure if this answers your questions, please bring more details regarding your scenario if necessary. Thank you in advance.

    Regards,
    Petar Mladenov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  9. Jason D
    Jason D avatar
    114 posts
    Member since:
    Jan 2011

    Posted 26 Mar 2018 in reply to Petar Mladenov Link to this post

    HI Petar. Thanks for your patience. I currently have everything working. I just want to find out if the problem is due to my lack of experience with threading or if there's something different that RadMap could do, as I've spent countless hours on this.

    I've attached a simplified sample (finally!). Change extension from gif to zip. It draws text with the following labels: 500, 1500, 2000. At zoom level 16, all labels should be visible. At zoom level 15, only 1000 should be visible. There are two calls to write "ZoomChanged" to the Console. If you use BeginInvoke, everything will work. If you use Invoke, it will not work. While it makes sense that BeginInvoke is correct, I don't understand why Invoke would break it. How to replicate:

    1. Start the app.
    2. Make the window tall enough that you can see at least two labels.
    3. Zoom out to level 15. At least 2 of the labels will be visible (incorrect). If you pan the map so that all the labels are outside of the window and then pan back, the map will now be correct.

    I see the same issue if I call Windows.Forms.Application.DoEvents. I also see the same issue if I use the VisualizatinLayer's Dispatcher.

  10. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3086 posts

    Posted 28 Mar 2018 Link to this post

    Hi Jason,

    Thank you for your isolation. I managed to reproduce the difference in behavior when using Dispatcher with BeginInvoke or Invoke. Also I noticed when nothing is performed in ZoomChanged, the behavior seems correct. From what I debugged in our RadMap solution I think this is a very complex threading issue. The code which adds and removes objects in VisualizationLayer is executed in background threads and they siglal each other with ManualResetEvents. My best guess is that Dispatcher.Invoke breaks the sequence of signals or some background thread receives false signal. One is for sure, this is a problem in RadMap, not in your application.

    Regards,
    Petar Mladenov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
Back to Top