MSDN Magazine - December 2007 - (Page 54) visually render the map’s contents. All data binding is done using implicit data contexts. In the case of the MasterCanvas control, this will always be set to an instance of the Map class. TranslateTransform binds its TranslateX and TranslateY properties to the equivalent properties on the Map class. Typically, these values are set on the map class to be the negated value of the upper left-hand corner of the Map’s bounding box. This has the effect of moving the map’s contents so that its upper left-hand A polygon with a missing corner corresponds with Fill brush is considered to the upper left-hand corner be a shell polygon, while a of the canvas. Similarly, the ScaleTransform binds its polygon with an explicitly set ScaleX and ScaleY properFill brush is considered to be ties to the associated propa filled polygon. erties on the Map class. In most cases, they are set to the ratio of the canvas’s width to the map’s width and the negated ratio of the canvas’s height to the map’s height. The following code shows the implementation of the ScaleTo method in the Map class: Public Sub ScaleTo(ByVal size As Size) If BoundingBox.Width 0 AndAlso BoundingBox.Height 0 Then ScaleX = size.Width / BoundingBox.Width ScaleY = -size.Height / BoundingBox.Height TranslateX = -BoundingBox.Left TranslateY = -BoundingBox.Bottom End If End Sub When given a Size structure that contains the height and width of MasterCanvas, the method will transform the map so that it is displayed entirely within the canvas. This method is called in response to the canvas’s SizeChanged event, thereby causing the map to scale to fill available space when the canvas’s containing window is resized: Private Sub WindowSizeChanged() Handles Me.SizeChanged If m_Map IsNot Nothing Then m_Map.ScaleTo(New Size(MasterCanvas.ActualWidth, MasterCanvas.ActualHeight)) End If End Sub Regions collection and utilizes the SimpleCanvasTemplate and RegionTemplate resources to define how everything is rendered. The SimpleCanvasTemplate, used for the ItemsControl’s ItemsPanel property, simply creates an empty Canvas. Its purpose is to define the container used to host each of the items created by the control’s ItemTemplate. A canvas is used primarily because canvases allow their contents to be explicitly positioned. Other “container controls,” such as a StackPanel, would attempt to apply automatic layout logic that ultimately would draw the map incorrectly. The RegionTemplate resource defines the visual layout used for each Region in the map. It does this by simply declaring a nested ItemsControl for each region and binding its ItemSource to the region’s Polygon collection. Like MapViewer, the nested ItemsControl defined in RegionTemplate uses a canvas for its ItemsPanel (in fact it reuses SimpleCanvasTemplate). Unlike MapViewer, however, it uses the PolygonTemplate resource to render its items. The PolygonTemplate resource defines a data template that renders a WPF polygon control given an instance of the MapPolygon class. It binds each Polygon’s Points collection to the Points property on the MapPolygon instance. It’s worth mentioning that the Polygon control has its Fill property explicitly set to Transparent. This is necessary to enable the Polygon to respond to many mouse events. WPF differentiates between polygons that have a Fill property set and those that do not. A polygon with a missing Fill brush is considered to be a shell polygon, while a polygon with an explicitly set Fill brush is considered to be a filled polygon. Mouse events such as MouseUp, MouseEnter, and MouseLeave for a filled polygon will fire when the mouse is inside the polygon’s interior. With shell polygons, the inside of the shape is not considered part of its definition. In that case, placing the mouse inside the polygon will not cause any of its mouse events to fire. By setting a polygon’s fill to transparent, however, it becomes possible to enable interaction with the mouse without obscuring other data drawn on the map. Another interesting aspect of the polygon template is that it uses declarative, trigger-based styles to drive the appearance of It’s worth noting that the ordering of the transformations within the containing TransformGroup is important. In particular, the TranslateTransformation must happen before the ScaleTransform. This allows arguments to both transformations to be specified in terms of the domain model, rather than in terms of the UI. If the ScaleTransform was listed first, then the values of the TranslateTransform would need to be specified in pixels rather than in kilometers, which would require an explicit conversion. Specifying the TranslateTransform first greatly simplifies the application’s object model. The ItemsControl is used to render the contents of the map onto the canvas. It behaves similarly to the ListBox control. In fact, ItemsControl is the base class for ListBox and defines most of its data binding behavior. Unlike the ListBox, however, the ItemsControl does not render items as list. This makes it much better suited for rendering maps, which clearly should not be displayed as a list. ItemsControl binds its ItemsSource property to the map’s 54 msdnmagazine Map LINQ Figure 11 Using a Mouse Event Trigger for Highlighting a Region
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.