This project is read-only.

Namespace: Microsoft.Maps.SpatialToolbox.Bing.Clustering

Supported Frameworks: Windows Store, WPF, WP8, WP8.1

The clustering section of this library provides a set of tools for implementing location clustering. Clustering of locations in Bing Maps consists of grouping together nearby locations into clusters. As the user zooms in the clusters break apart to reveal the individual locations. The goal of this process is to reduce the number of pushpins that are displayed on the map at any given time. This results in better performance by the map control and also a better experience for the user as they will be able to see the map and not be overwhelmed with pushpins filling the screen. By implementing clustering in the native version of Bing Maps you can easily increase the number of pushpins you can add to the map before any noticeable performance issue occurs from a couple thousand to 30,000 or more. Here is a screenshot of 5,000 pushpins on a map.


Now here is the same 5,000 pushpins being displayed using clustering.


The clusters are shown in red to make them easier to see. The blue pushpins are individual locations that had no other pushpins close by.

There are several different algorithms that can be used to cluster pushpins. In this library I have provided to methods; Grid and Point based clustering. Grid based clustering breaks up the current viewport into a grid of a defined size. All pushpins inside of a single grid cell are grouped together as a cluster. The cluster is then displayed on the map at the mean average location of all the items in the cluster as this looks the most natural. This algorithm is very fast and ideal for large data sets upwards of 50,000 locations. However, whenever the map is moved, even slightly, a new grid is created based on the new viewport and the data re-clustered. This can result in locations moving from one grid cell to another which can cause a pushpin to appear to jump around on the screen. The grid based algorithm may also have pushpins overlap if a number of locations are on either side of the edge of a grid cell. The point base algorithm is a bit more complex and starts off by taking the first location in the data set and searches the data set for all locations that are within a certain radius of that location. The algorithm then grabs the next, un-clustered location in the data set and searches the list again. This repeats until all items in the data set have been clustered. This extra complexity comes at a cost and I have found it works well with data sets containing up to 30,000 locations. One benefit of this approach is that there is no pushpin jumping effect and a lot less overlapping of pushpins as seen with the grid based cluster algorithm.

The clustering functionality in this library consists of a number of different classes as described here.




An object used to store information about a cluster.


A layer that can be added to the map like a MapLayer that implements the clustering logic to a data set.


An enumerator which is used to specify the type of clustering algorithm to be used by the ClusteringLayer.


A class used to represent a single data point to be clustered.


A class that represents a collection of items to be clustered by the ClusteringLayer.

The ClusteringLayer is the main class that does all the heavy lifting. This class can be added to the map just like a MapLayer. This class has three public properties as defined below.




The pixel radius to use in the clustering algorithm. The smaller the radius the slower the algorithms become but the more natural the data looks.


An enumerator of type ClusteringType which indicates the type of clustering algorithm to used; Grid or Point based clustering.


A collection of location items to cluster.

: It is best to first load all items into a LocationItemCollection object first and then add them to the ClusterLayer Items property using the AddRange method as the Items property will force a recluster of the data every time it’s data changes.

The ClusterLayer class also has two events; CreateItemPushpin and CreateClusteredItemPushpin. These events allow you to specify callback methods that are used to generate the pushpins needed to represent a single or clustered location.

The following is an example of how to implement the ClusteringLayer.


using Microsoft.Maps.SpatialToolbox.Bing.Clustering;

private void ClusterData_Clicked(object sender, RoutedEventArgs e)
//Create an instance of the clustering layer
var layer = new ClusteringLayer();
layer.ClusterType = ClusteringType.Point;

//Add event handlers to create the pushpins
layer.CreateItemPushpin += CreateItemPushpin;
layer.CreateClusteredItemPushpin += CreateClusteredItemPushpin;

//Add data to layer, where _mockdata is a ItemLocationCollection

private UIElement CreateItemPushpin(object item)
var pin = new Pushpin()
Tag = item

pin.Tapped += pin_Tapped;

return pin;

private UIElement CreateClusteredItemPushpin(ClusteredPoint clusterInfo)
var pin = new Pushpin()
Background = new SolidColorBrush(Colors.Red),
Text = "+",
Tag = clusterInfo

pin.Tapped += pin_Tapped;

return pin;

Visual Basic

Imports Microsoft.Maps.SpatialToolbox.Bing.Clustering

Private Sub PointClusterData_Clicked(sender As Object, e As RoutedEventArgs)
'Create an instance of clustering layer
Dim layer = New ClusteringLayer()
layer. ClusterType = ClusteringType.Point

'Add event handlers to create the pushpins
AddHandler layer.CreateItemPushpin, AddressOf CreateItemPushpin
AddHandler layer.CreateClusteredItemPushpin, AddressOf CreateClusteredItemPushpin

' Add data to layer, where _mockdata is a ItemLocationCollection
End Sub

Private Function CreateItemPushpin(item As Object) As UIElement
Dim pin = New Pushpin()
pin.Tag = item
Return pin
End Function

Private Function CreateClusteredItemPushpin(clusterInfo As ClusteredPoint) As UIElement
Dim pin = New Pushpin()
pin.Background = New SolidColorBrush(Colors.Red)
pin.Text = "+"
pin.Tag = clusterInfo
Return pin
End Function

Last edited Aug 12, 2014 at 3:53 PM by rbrundritt, version 2