Skip to content

Files

Latest commit

Feb 24, 2022
c99b441 · Feb 24, 2022

History

History
349 lines (312 loc) · 12.7 KB

howto-wraparound-virtualization-visualizationlayer.md

File metadata and controls

349 lines (312 loc) · 12.7 KB
title page_title description slug tags published position
Wraparound with Virtualization in VisualizationLayer
Wraparound with Virtualization in VisualizationLayer
Check our "Wraparound with Virtualization in VisualizationLayer" documentation article for the RadMap {{ site.framework_name }} control.
radmap-howto-wraparound-virtualization-visualizationlayer
wraparound,virtualization,visualizationlayer,map
true
10

Wraparound with Virtualization in VisualizationLayer

When using wraparound functionality, the virtualization of the RadMap control needs to be further customized.

Wraparound with Virtualization in VisualizationLayer

In order to enable the UI Virtualization feature, you should configure the ZoomLevelGridList object and you should set the VirtualizationSource property of the [Visualization Layer]({%slug radmap-features-virtualization-layer%}). The ZoomLevelGridList property allows dividing the map into regions. The data provided to the VisualizationLayer should be wrapped in a class that implements the IMapItemsVirtualizationSource interface. This interface contains a MapItemsRequest() method, which is used by the VisualizationLayer to request new data whenever the ZoomLevel or Center properties of the RadMap control are changed. The event arguments are of type MapItemsRequestEventArgs which give you the currently visible area of the map. This method generally serves as an event handler and you have to calculate and decide which objects to be displayed in the given viewport.

In WrapAround mode, this portion will have Longitude value exceeding the valid geographical boundaries (-180; 180). The RadMap control provides public methods which you can use to normalize such locations. You can take a look a the [Location Conversion]({%slug radmap-features-wraparound%}) section in the WrapAround help article.

In the next part of this article, we will display points of interest (POIs) over the cities (Berlin, London, Amsterdam, Madrid, Barcelona, Rome) in the map in MVVM scenario and set the virtualization when the wraparound mode of the map is on. In Example 1 we will specify the business object which will hold the Longitude, Latitude values, the name of the cities and their location.

[C#] Example 1: Business object

{{region c#-radmap-radmap-howto-wraparound-virtualization-visualizationlayer_0}} public class CityLocation : ViewModelBase { private double _lattitude; private double _longitude; private string _cityName; public CityLocation(double latitude, double longitude, string cityName) { this.Latitude = latitude; this.Longitude = longitude; this.CityName = cityName; }

    public double Latitude
    {
        get
        {
            return this.\_lattitude;
        }
        set
        {
            Location old = this.Location;
            this.\_lattitude = value;
            this.OnPropertyChanged("Latitude");
            this.OnPropertyChanged("Location");
        }
    }

    public double Longitude
    {
        get
        {
            return this.\_longitude;
        }
        set
        {
            Location old = this.Location;

            this.\_longitude = value;
            this.OnPropertyChanged("Longitude");
            this.OnPropertyChanged("Location");
        }
    }

    public Location Location
    {
        get
        {
            return new Location(this.Latitude, this.Longitude);
        }
    }

    public string CityName
    {
        get
        {
            return this.\_cityName;
        }
        set
        {
            this.\_cityName = value;
            this.OnPropertyChanged("CityName");
        }
    }
}

{{endregion}}

Then you can create custom class which implement the IMapItemsVirtualizationSource interface. In the handler of the MapItemRequest() event you can get the LocationRect region from the arguments and normalize the region by using GetCoercedLocation method of RadMap. Then you need to calculate which cities should be displayed in the normalized region.

[C#] Example 2: Custom class

{{region c#-radmap-radmap-howto-wraparound-virtualization-visualizationlayer_1}} public class VirtualizationSource : IMapItemsVirtualizationSource { private bool isFirstRequest = true; private RadMap map; private ExampleViewModel dataContext;

    public VirtualizationSource(ExampleViewModel dataContext)
    {
        this.dataContext = dataContext;
    }

    public void MapItemsRequest(object sender, MapItemsRequestEventArgs eventArgs)
    {
        if (this.isFirstRequest)
        {
            this.map = eventArgs.Layer.MapControl;
            this.isFirstRequest = false;
        }

        double minZoom = eventArgs.MinZoom;
        // Coercing (normalizing) the map portion of the request in normal [-180; 180] longitude range.
        Location upperLeft = map.GetCoercedLocation(eventArgs.UpperLeft);
        Location lowerRight = map.GetCoercedLocation(eventArgs.LowerRight);

        if (this.dataContext == null)
            return;
        List<CityLocation> list = this.dataContext.GetCities(
              upperLeft.Latitude,
              upperLeft.Longitude,
              lowerRight.Latitude,
              lowerRight.Longitude);
        dataContext.SetCities(list, eventArgs);
    }
}

{{endregion}}

In the ViewModel we shift the locations by shifting their longitudes using SetCities() and TryGetLongitudeMatchInRange() methods.

[C#] Example 3: Create view model

{{region c#-radmap-radmap-howto-wraparound-virtualization-visualizationlayer_2}} public class ExampleViewModel : ViewModelBase { private MapProviderBase mapProvider; public List PinLocations { get; set; } public ExampleViewModel() { SetProvider(); this.ZoomLevel = 3; this.Center = new Location(52.5243700, 13.4105300); PinLocations = new List(); GetLocations(); }

	private void GetLocations()
	{
		PinLocations.Add(new CityLocation(52.52437, 13.41053, "Berlin"));
		PinLocations.Add(new CityLocation(51.50853, -0.12574,"London"));
		PinLocations.Add(new CityLocation(52.37403, 4.88969, "Amsterdam"));
		PinLocations.Add(new CityLocation(40.41650, -3.70256, "Madrid"));
		PinLocations.Add(new CityLocation(41.38879, 2.15899, "Barcelona"));
		PinLocations.Add(new CityLocation(41.89193, 12.51133, "Rome"));           
	}

	private void SetProvider()
	{
		OpenStreetMapProvider provider = new OpenStreetMapProvider();
		provider.Layer = OpenStreetMapLayer.Humanitarian;
		this.mapProvider = provider;
	}

	public MapProviderBase Provider
	{
		get
		{
			return this.mapProvider;
		}
	}

	private int \_zoomLevel;
	public int ZoomLevel
	{
		get
		{
			return this.\_zoomLevel;
		}
		set
		{
			if (this.\_zoomLevel != value)
			{
				this.\_zoomLevel = value;
				this.OnPropertyChanged("ZoomLevel");
			}
		}
	}

	private Location \_center;
	public Location Center
	{
		get
		{
			return this.\_center;
		}
		set
		{
			if (this.\_center != value)
			{
				this.\_center = value;
				this.OnPropertyChanged("Center");
			}
		}
	}
	public List<CityLocation> GetCities(double upperLeftLat, double upperLeftLong, double lowerRightLat, double lowerRightLong)
	{
		List<CityLocation> locations = new List<CityLocation>();  

		var latLonCondition = PinLocations.Where(x=>
		x.Latitude < upperLeftLat && 
		x.Latitude > lowerRightLat &&
		x.Longitude >upperLeftLong &&
		x.Longitude < lowerRightLong
		);           
		foreach (var item in latLonCondition)
		{
			locations.Add(new CityLocation(item.Latitude,item.Longitude,item.CityName));
		}              
		return locations;

	}
	/// <summary>
	/// Callback of the GetCities async call.
	/// The method uses the web service response to building objects on the dynamic layer.
	/// </summary>
	internal void SetCities(List<CityLocation> list, MapItemsRequestEventArgs request)
	{
		if (list.Count == 0)
			return;
		// Shifts the cities to the current portion of the request.
		foreach (CityLocation cityLocation in list)
		{
			// Shifts the city to the current portion of the request.
			cityLocation.Longitude = this.TryGetLongitudeMatchInRange(cityLocation.Longitude, request.UpperLeft.Longitude, request.LowerRight.Longitude);
		}
		request.CompleteItemsRequest(list);
	}

	private double TryGetLongitudeMatchInRange(double longitude, double left, double right)
	{
		if (left <= longitude && longitude <= right)
			return longitude;

		double range = this.mapProvider.SpatialReference.MaxLongitude - this.mapProvider.SpatialReference.MinLongitude;

		while (longitude < left)
		{
			longitude += range;
		}
		while (longitude > right)
		{
			longitude -= range;
		}
		return longitude;
	}
}

{{endregion}}

Then you can declare the RadMap control in XAML where you can specify custom DataTemplate for the POI and then you can set it to the ItemTemplate property of the VisualizationLayer.

[XAML] Example 4: Declare RadMap in XAML

{{region c#-radmap-radmap-howto-wraparound-virtualization-visualizationlayer_3}} <Window.Resources> <local:ExampleViewModel x:Key="ViewModel" /> </Window.Resources> <telerik:RadMap x:Name="radMap" WrapAround="True" Provider="{Binding Provider}" Center="{Binding Center, Mode=TwoWay}" ZoomLevel="{Binding ZoomLevel, Mode=TwoWay}"
MiniMapExpanderVisibility="Collapsed">

        <telerik:VisualizationLayer Name="visualizationLayer" 
                                    ItemTemplate="{StaticResource pointTemplate}">
            <telerik:VisualizationLayer.ZoomLevelGridList>
                <telerik:ZoomLevelGrid MinZoom="3" />
                <telerik:ZoomLevelGrid MinZoom="9" />
            </telerik:VisualizationLayer.ZoomLevelGridList>
        </telerik:VisualizationLayer>
    </telerik:RadMap>
</Grid>

{{endregion}}

The final step is to set the custom VirtualizationSource class to the VirtualizationSource property of the VisualizationLayer. You can check Example 5.

[C#] Example 5: Set the custom VirtualizationSource class to the VirtualizationSource property

{{region c#-radmap-radmap-howto-wraparound-virtualization-visualizationlayer_4}} public MainWindow() { InitializeComponent(); this.visualizationLayer.VirtualizationSource = new VirtualizationSource(this.LayoutRoot.DataContext as ExampleViewModel); } {{endregion}}

Similar and more complex example you can find in our GitHub repository.

See Also

  • [Bing Map Rest Provider]({%slug radmap-features-providers-bing-rest-map%})
  • [VisualizationLayer - Introduction]({%slug radmap-visualization-layer-introduction%})
  • [Wraparound] ({%slug radmap-features-wraparound%})