(Continued from Part 2.This and the other posts in this series is material I’ve written for Programming Windows Store Apps in HTML, CSS, and JavaScript, Second Edition.)

A map (IMap<K, V>) and its read-only map view companion (IMapView<K, V>) are additional derivations of the basic iterator. A map is composed of key-value pairs, where the keys and values can both be arbitrary types. [Footenote: Each pair is described by the IKeyValuePair<K, V> interface, but you don’t encounter that construct explicitly in JavaScript. Also, the IObservableMap<K, V> interface is also meant for other languages and not used in JavaScript.] A closely related construct is the property set (IPropertySet), which relates to the map. The difference is that maps and map views are used (like vectors) to return collections from WinRT APIs and to handle certain properties of WinRT objects. Property sets, for their part, as used (like basic iterators) as input arguments to WinRT APIs.

It’s important to note right up front that maps and property sets are not projected as arrays in JavaScript. They do support value lookup through the [ ] operator, but otherwise do not have array methods. A map, instead, has methods (from IMap) called lookup (same as [ ]), insert, remove, clear, and hasKey, along with a size property and a getView method like the vector. A map view shares hasKey, lookup, and size, and adds a split method. You can also pass a map or map view to Object.keys to retrieve an array of keys.

A property set has a more extensive interface, but let me come back to that in a bit.

The generic term for maps and property sets alike is a dictionary. A dictionary does just what the word means in colloquial language: it lets you look up an item (e.g. a definition) in a collection (the dictionary) by a key (such as a word). This is very useful when the collection you’re working with doesn’t store items in a linear or indexed array, or doesn’t have a need to do so. For example, when working with the Windows.Storage.Pickers.FileSavePicker class, you give the user a choice of file types through its fileTypeChoices property. This property is very interesting because its type is IMap<String, IVector>, meaning that it’s a map between a string key and a value that is itself an array. This makes sense, because you want to use something like “JPEG” for a key while yet mapping that single key to a group of values like “.jpg” and “.jpeg”.

Maps are also used extensively when working with file properties, where you have access to a deeper hierarchy of metadata that’s composed of key-value pairs. This is the same metadata that you can explore if you right click on a file in Windows Explorer and click the details tab, as shown here for a picture I took on a trip to Egypt where the camera recorded exposure details and so forth:

image properties

The Windows.Storage.FileProperties API is how you get to all this metadata. Images provide an ImageProperties object, whose retrievePropertiesAsync produces a map containing the metadata. You can play with this in the Simple Imaging sample if you’d like, where once you’ve obtained a map you can access individual properties by name (retrievedProps is the map):

retrievedProps[“System.Photo.ExposureTime”]

On the flip side of this metadata scene is where we encounter property sets. Again, these are a form of dictionary like maps, but one that an app needs to create for input to methods like ImageProperties.savePropertiesAsync. This is why Windows.Foundation.Collections has a concrete PropertySet class and not just an interface, because then we can new up an instance like so:

var properties = new Windows.Foundation.Collections.PropertySet();

and create key-value pairs with the [ ] operator:

properties[“System.GPS.LatitudeNumerator”] = latNum;

or with the insert method:

properties.insert(“System.GPS.LatitudeNumerator”, latNum);

Be mindful that while the documentation for PropertySet lists quite a few methods and properties, only some of them are projected into JavaScript:

  • Properties: size
  • Lookup methods: [ ], lookup, hasKey, first (returns an iterator for the key-value pairs)
  • Manipulation methods: clear, insert, remove
  • Other: getView (retrieves a map view) and the mapChanged event

In summary, then, maps and property sets are distinct collection constructs that must be worked with through their own methods and properties. Vectors, on the other hand, are projected into JavaScript as an array and are thus suitable for data binding through WinJS.Binding.List. If you want to bind to a map or property set, on the other hand, you’ll need to maintain an array copy.


Comments are closed