The map is capable of displaying complex sets of data using a variety of mechanism like choropleth maps, and distribution scales, but sometimes all you want to do is color a map element a specific color based a condition such as a Map Element property value. In this article I will show you how you can use the xamWebMaps data binding capabilities and its event model to conditionally format Map Elements.
I am going to get started by setting up a base map that shows all of the states in the Unites States. The following is the code to set up a basic map that reads a shapefile containing all of the states, and maps the STATE_NAME column from the shapefile dbf to the Map Elements Name property.
if you are new to data binding with the xamWebMap, I suggest you check out my article, Data Display using xamWebMap.
<igMap:XamWebMap x:Name="XamWebMap1"> <igMap:XamWebMap.Layers> <igMap:MapLayer x:Name="usa"> <igMap:MapLayer.Reader> <igMap:ShapeFileReader Uri="USA_ST" DataMapping="Name=STATE_NAME" /> </igMap:MapLayer.Reader> </igMap:MapLayer> </igMap:XamWebMap.Layers> </igMap:XamWebMap>
This bit of XAML gets us a map that looks like this:
Now I have to bind the data that I want to base my formatting condition logic on. That data is kept in a class called RedVsBlue, and is exposed by a static property that returns an ObservableCollection of KeyValuePair objects. While I have hard coded the data for this article, it could just have easily come from an external data source such as a web service. Below is a snippet of the class:
public class RedVsBlue { static ObservableCollection<KeyValuePair<string, string>> _redvblue; public static ObservableCollection<KeyValuePair<string, string>> GetRedsAndBlues { get { if (_redvblue == null) { _redvblue = new ObservableCollection<KeyValuePair<string, string>>(); _redvblue.Add( new KeyValuePair<string, string>("Alabama", "R")); _redvblue.Add( new KeyValuePair<string, string>("Alaska", "D")); // ... The rest of the states are defined here // ... removed for clarity ... } return _redvblue; } } }
Each KeyValuePair object sets the state name as its Key and the political party that won the state in the 2004 U.S. presidential election as its Value.
To bind this data, in the xamWebMaps loaded event, I define a data mapping on my map layer and set its DataSource:
private void XamWebMap1_Loaded(object sender, RoutedEventArgs e) { DataMapping mapping = new DataMapping(); mapping.Add(new DataMappingPair("Name", "Key")); mapping.Add(new DataMappingPair("Party", "Value")); this.XamWebMap1.Layers["usa"].DataMapping = mapping; this.XamWebMap1.Layers["usa"].DataSource = RedVsBlue.GetRedsAndBlues; }
The DataMapping object allows me to define the mapping pairs for the layer. In this case, I am mapping the KeyValuePair’s Key property to the MapElements Name property, and its Value property to a map element pseudo property called Party.
Finally, I need to create some conditional formatting logic. To do that, I can use the maps ElementPropertyChanged event. This event is raised any time any property of any Map Element in the map changes.
private void XamWebMap1_ElementPropertyChanged( object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Party") { MapElement element = sender as MapElement; switch (element.GetProperty("Party").ToString()) { case "R": element.Fill = new SolidColorBrush(Colors.Red); break; case "D": element.Fill = new SolidColorBrush(Colors.Blue); break; default: element.Fill = new SolidColorBrush(Colors.Gray); break; } } }
In the ElementPropertyChanged event, the first thing I need to do is see what property actually changed since I only want to listen for when the Map Elements Party property changes. When I detect that the Party property has changed, I get the Map Element that the value has changed for, and based on the value of its Party property, set its Fill color to a new SolidColorBrush.
Now when I run the application, I can clearly see how individual states voted.