This is a migrated thread and some comments may be shown as answers.

DynamicLayer Visible Items

7 Answers 182 Views
Map
This is a migrated thread and some comments may be shown as answers.
Adrien
Top achievements
Rank 1
Adrien asked on 29 Nov 2010, 04:00 PM
Hello,

I am using the dynamic layer approach to display pushpins onto the map.

I need to change a part of the displayed content of the pushpins depending on the exact set of visible pushpins. Example: say the dynamic layer has loaded 3 pushpins, the content of each of them will be different whether only one is visible, or two are visible, or the three of them.

I thus need to refresh the content of the pushpins in any of these events:
i) a small change of the map center, which generally does not cause the dynamic layer to request new data but makes some pushpins appear (resp. disappear) because they were (resp. become) out of the view field
ii) a sufficiently large change of the map center, which does cause the dynamic layer to request new data and displays new pushpins
-- I need to know which exactly pushpins are being visible as some part of the content of the pushpins depends precisely on the current state of the visible pushpins set. --

Thus, my first attempt was to
- add an event handler to the CenterChanged event of the RadMap control to take care of the point (i), using the Map.LocationRect property to know which pushpins are being seen, and update their content consequently.
- directly treat the case (ii) in the ItemsRequest method of the class implementing IMapDynamicSource

However, this second step is problematic as the ItemsRequest method might be called several times if multiple dynamic regions are being seen in the current view field. I cannot update the pushpins content in the ItemsRequest method as other pushpins might arrive in a subsequent method call.
In other words, I need a way to know when a new set of data has been loaded by the dynamic layer and to access this entire set at once.

As far as I know, there is no event such as LayerLoaded in the dynamic layer, which would fire when all the data has been loaded.

Do you have an advice to solve this problem?

Thank you in advance.

Adrien

7 Answers, 1 is accepted

Sort by
0
Andrey
Telerik team
answered on 01 Dec 2010, 04:59 PM
Hi Adrien,

You can use the functionality for CenterChanged event from the ItemsRequest method.
The sample code is below.
public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        this.dynamicLayer.ZoomGridList.Add(new ZoomGrid(2, 2, 3));
        this.dynamicLayer.ZoomGridList.Add(new ZoomGrid(36, 72, 9));

        
// set dynamic source
        this.dynamicLayer.DynamicSource = new DynamicSource(this);
    }

    
private void radMap_CenterChanged(object sender, EventArgs e)
    {
        this.UpdateContent();
    }

    
public void UpdateContent()
    {
        // update content of visible items
    }

    
private class DynamicSource : IMapDynamicSource
    {
        private MainPage page;

        
public DynamicSource(MainPage page)
        {
            this.page = page;
        }

        
public void ItemsRequest(object sender, ItemsRequestEventArgs e)
        {
            // ...
            this.page.UpdateContent();
        }
    }
}

Kind regards,
Andrey Murzov
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
Adrien
Top achievements
Rank 1
answered on 11 Dec 2010, 08:54 AM
Dear Andrey,

I already thought about this solution but I think it does not work for the following reason:
Depending on the region (and the level of zoom) one is currently seeing on the map, it might correspond to multiple "ZoomGrid" rectangles. In fact, if the map center is approximately equal to the corner of one ZoomGrid, the dynamic layer will have to load the data from the 3 other visible ZoomGrids. There is thus 4 calls to the ItemRequest method (implementing IMapDynamicSource) as far as I could see.

Making my previous question simpler: how can know when the dynamic layer has finished loading all the data - whatever the number of ZoomGrid currently visible?

Also this is important if I want to block the UI or show a busy indicator while the dynamic layer is loading items: I want the busy state to start on the first data request (<=> first ZoomGrid visible) and stay there until the end of the last request (<=> if there are multiple ZoomGrids visible).

Thank you for your help.

Adrien
0
Andrey
Telerik team
answered on 15 Dec 2010, 08:45 AM
Hello Adrien,

I think you can use the RadMap.ZoomChanging, ZoomingFinished, CenterChanging and PanningFinished events. The dynamic layer calls ItemsRequest method between pairs of these events.
You can know that the request process is started by the RadMap.ZoomChanging and CenterChanging events.
When one of these events occurs and then the ItemsRequest method is called then you can know that requests are started. When ZoomingFinished and / or PanningFinished event occurs then all requests are called.

Best wishes,
Andrey Murzov
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
Adrien
Top achievements
Rank 1
answered on 15 Dec 2010, 05:55 PM
Hello Andrey,

Thanks for your answer. However, this is not exactly what I try to determine:

I need to know when all the requests done by the dynamic layer are completed (<=> the data of each request has been received by the client), and -not- when all the requests have been started.

As I wrote in my precedent message, I need to achieve some work on the requested data which can only be done when all the data has arrived. It would be trivial if the method ItemRequests was called exactly once whatever the map view, but as it can be called several times if multiple ZoomGrid are being seen, I need some event to notify me when all the data has arrived, so that I can run the algorithm.

Thanks
0
Andrey
Telerik team
answered on 17 Dec 2010, 02:13 PM
Hi Adrien,

The dynamic layer does not trace requests.
If you need to check that all requests are complete, then you can do it in the DynamicSource implementation.
Usually each call of ItemsRequest completes request by the CompleteItemsRequest method. I think you can register each request when it starts and then to unregister it when it complete. For example you can use a counter for this purpose (register of request increments it and the unregister operation decrements). If the request is unregistered and the counter contains 0, then it indicates that all requests are complete.
The sample code is below.
private class DynamicSource : IMapDynamicSource
{
    private static int requestCounter = 0;

    
public void ItemsRequest(object sender, ItemsRequestEventArgs e)
    {
        double minZoom = e.MinZoom;
        Location upperLeft = e.UpperLeft;
        Location lowerRight = e.LowerRight;

        
if (minZoom == 3)
        {
            // register request
            RegisterRequest();

            
// request data from WCF service
            DataServiceClient client = new DataServiceClient(binding, address);
            client.GetDataCompleted += this.GetDataCompleted;
            client.GetDataAsync(minZoom, upperLeft.Latitude, upperLeft.Longitude,
                lowerRight.Latitude, lowerRight.Longitude, e);
        }
    }

    
private static void RegisterRequest()
    {
        if (requestCounter == 0)
        {
            // first request starts
        }
        requestCounter++;
    }

    
private static void UnregisterRequest()
    {
        requestCounter--;
        if (requestCounter == 0)
        {
            // all requests complete
        }
    }

    
private void GetDataCompleted(object sender, GetDataCompletedEventArgs e)
    {
        List<object> objects = new List<object>();

        
// retrive data and add shapes to the list
        // ...

        
// complete request
        (e.UserState as ItemsRequestEventArgs).CompleteItemsRequest(objects);

        
// unregister request
        UnregisterRequest();
    }
}

Regards,
Andrey Murzov
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
Nuno
Top achievements
Rank 1
answered on 14 Jan 2011, 10:27 PM
Hi Andrey,

I'm a Telerik fan and I need your help because I'm having difficulties updating my code to work with the Q3 release. It was working fine with the Q2.
The ItemsRequest method stopped working because its signature has changed (because IMapDynamicSource changed), we don't need the old signature with the Action callback anymore. Why?

One of the things I noticed (after inspecting for a couple hours) is that I couldn't add ZoomGrid instances to the dynamicLayer like this anymore (Q2 way):

this

 

 

.dynamicLayer.ZoomGridList.Add(new ZoomGrid() { MinZoom = regionsLevelZoom });
...
In order to get it calling the ItemsRequest method must be like this:

 

this

 

 

.dynamicLayer.ZoomGridList.Add(new ZoomGrid(1, 1, regionsLevelZoom));
...
Also, I'm not using a webservice to request data. This means I can't do this as in the Items Virtualization demo:

 

    ItemsRequestEventArgs request = e.UserState as ItemsRequestEventArgs;
    request.CompleteItemsRequest(objects);

To overcome this I had to pass the ItemsRequestEventArgs parameter back like this:

this.page._dynamicSource_DynamicSourceRegions(query, e);

and then in that method do something like this:
...
ItemsRequestEventArgs request = e;
request.CompleteItemsRequest(pinPoints);

 

 

 

Another thing that seems to have changed is importing KML data. I followed this link:
http://demos.telerik.com/silverlight/#Map/KmlImport

It loads my regions ok but when I start zooming in or out it has some odd behavior. Starts shaking and blinking until it gets to the desired zoom level, and when it gets to a very detailed zoom (like city, street) KML layers are not visible anymore. Why is this happening?
(Is there any special reason users can't zoom in/out in the mentioned KmlImport demo??)

In my opinion it should be nice if Telerik updates the only existent information about the dynamic layer:
http://www.telerik.com/help/silverlight/radmap-features-dynamic-layer.html
because it still provides us with a simple example using the Q2 away to work with it:

ItemsRequest( double minZoom, double maxZoom, Location upperLeft, Location lowerRight, Action<System.Collections.ICollection> callback )
...

Can you please explain a little more what changed in the Q3 release regarding RadMaps and why?

Thank you.

Nuno Senica

0
Andrey
Telerik team
answered on 20 Jan 2011, 09:01 AM
Hello Nuno,

In version 2010.Q3 we completely redesigned engine of the information layer to increase its panning and zooming performance on large data arrays. Now it can handle up to 1000 locations (compare with 150 in previous version) or map shapes with up to 100000 total points (compare with 10000 in previous version).

The dynamic layer was redesigned also. Currently it hides objects in invisible regions to increase performance. The dynamic layer is oriented to asynchronous data requests. So, at the moment when a data is obtained and the shapes should be passed to the dynamic layer then it should know the parameters which were passed with request (zoom level and region). These parameters are required, because the map environment such as zoom level and region could be changed. So, it will be incorrect to add shapes for example when zoom level has been changed to another according to ZoomGridList. Unfortunately it was impossible with simple callback from the Q2 version.

As a simple migration way you can change the code of dynamic source class to use a code which was designed for Q2 just using new delegate type instead of Action<System.Collections.ICollection> for callback. The sample code is below.
public class DynamicSource : IMapDynamicSource
{
    // …
    public delegate void CallbackDelegate(IEnumerable<object> items);

    
public void ItemsRequest(object sender, ItemsRequestEventArgs e)
    {
        this.ItemsRequest(e.MinZoom, e.MaxZoom, e.UpperLeft, e.LowerRight, e.CompleteItemsRequest);
    }

    
// Q2 style items request
    public void ItemsRequest(double minZoom, double maxZoom, Location upperLeft, Location lowerRight, CallbackDelegate callback)
    {
        List<object> objects = new List<object>();
        // …
        callback(objects);
    }
}

The KML layers are not visible for detailed zoom levels in example, because the Silverlight has some restriction with shapes calculation. In fact it uses the short type values for them. So, if the shape has a size that becomes larger than max short value while zooming then it is calculated wrong.

All the best,
Andrey Murzov
the Telerik team
Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
Tags
Map
Asked by
Adrien
Top achievements
Rank 1
Answers by
Andrey
Telerik team
Adrien
Top achievements
Rank 1
Nuno
Top achievements
Rank 1
Share this question
or