Developer Reference ENCX and WPF

ENCX includes sample controls for WPF in .NET Framework and .NET Core.

Getting the samples

The samples are included with the ENCX installer download.

  • Encx.Wpf defines two WPF controls, one for S57 and one for raster charts.
  • Encx.Wpf.S57Example - a quick example of how to use the S57Control.
  • Encx.Wpf.RasExample - a quick example of how to use the RasControl.
  • ENCX.CoreWPF defines two WPF controls, one for S57 and one for raster charts.
  • ENCX.CoreWPF.S57Example - a quick example of how to use the S57Control.
  • ENCX.CoreWPF.RasExample - a quick example of how to use the RasControl.

Note that the ENCX.CoreWPF solution contains WinForms controls and samples as well was WPF controls.

To get started, copy the appropriate folder containing the solution you want to try out to a suitable location, open the solution file, and run the *Wpf.S57Example.

All being well, you are now looking at a chart of the River Humber, England. Along the bottom of the window, we have some labels that are databound to properties of the chart drawing control. In the top right we have a North arrow which you should be able to drag to rotate the chart, and finally we have a few simple WPF shapes overlaid onto the display.

How does it work?

The projects contain controls (Encx.Wpf.S57Control / ENCX.CoreWPF.S57Control) that we use to wrap some ENCX S57 chart drawing functionality in a WPF-friendly way.

Various properties are provided to allow databinding but we had no appetite to wrap up every method of the ENCX S57Draw object, so some operations require you to manipulate that directly — the S57Draw property gives you access to this. After you do anything with the S57Draw object you must call UpdateBitmap() in order to ask ENCX to redraw the chart. Every time the chart is redrawn, the control fires the OnBitmapUpdated event — this helps you know when to update the position of any overlaid visuals.

Moving on to the S57Example projects and MainWindow.xaml, we can start to see how the sample app fits together — we simply declare an S57Control along with a Canvas upon which we draw our overlaid shapes.

Our NorthArrow control is placed at the top right of the window. (I won't go into any detail on the NorthArrow, as it's incidental to getting ENCX to work with WPF, but the code is there if you want to take a look.)

We also have a few TextBlocks bound to properties of the S57Control.

With the XAML already written, we only need a few lines of actual code to get our first chart displayed. The bare minimum is to create an ENCX.Library and an ENCX.S57Manager, then set the appropriate properties on the S57Control.

After that, we just need to set the display scale of the control and tell it the geo-position we'd like to look at (via S57Control.UpdatePosition()). This is enough to display a chart which can be drag-scrolled and zoomed with the mousewheel.

Our example app does a little bit more than that:

  • We alter the chart display settings to make the charts easier on the eye, and attach an event handler to make our chart rotate with the NorthArrow.
  • We also subscribe to S57Control's OnBitmapUpdated event to tell us when to update the position of our WPF shapes in the canvas.

Conversion from geographical space into pixel space and detecting when a geographical point is out of view is efficiently done by the GeoPix object, accessed via S57Control.S57Draw.GeoPix.

The great thing about overlaying shapes in this way is that the shapes are proper WPF objects that can efficiently leverage visual effects, styling, hit testing, event bubbling and all the other things that make WPF desirable — we demonstrate this by setting a Style, ToolTip and MouseDown event handler for each shape. Clicking a shape should centre it in the view, and all the shapes have a common base style which adds a drop shadow (I understand better-looking effects are available!)

Making it better

You can set the DisplayScale property when you declare the S57Control in XAML; the same is not currently possible for GeographicCenter. The missing link is an IValueConverter that provides a conversion between a string representation of a latitude/longitude and GeoPoint. It's also quite possible for the GeographicCenter property to be made animatable to allow you to 'fly' from place to place…