MVVM is your friend to get sensor data in Windows Phone 7
See my original post at https://kevinashley.com
There’s little doubt that MVVM pattern makes your life as a developer a lot easier. There’re several MVVM frameworks for Windows Phone that make it happen:
- MVVM Light https://mvvmlight.codeplex.com
- Caliburn https://caliburnmicro.codeplex.com
- Catel https://catel.codeplex.com
- Cinch https://cinch.codeplex.com
and a few others (please, comment if you don’t find your favorite one!).
In my everyday life I use MVVM Light a lot, but today I’d like to explore new trends in the latest editions of some MVVM frameworks. I’m talking about using MVVM to support sensor data and services: accelerometer, camera, compass, gyro, location and others.
Focus on Catel primarily, because it brings a lot of support for MVVM from the sensors prospective, and also because I overlooked it somehow in the past.
Geert van Horrik, the author of Catel did a fantastic work building and documenting the framework on Code Project and in this documentation on his Web site. Specifically, I couldn’t stop from quoting this impressive side-by-side comparison sheet:
We will also discuss testing sensor data with Catel MVVM framework.
Building a sensor MVVM app
All code is available from Catel’s sample code project https://catelexamples.codeplex.com/
The tools are easily available as NuGet packages, or as a separate download from Codeplex. Just make sure NuGet is installed, then in the Visual Studio, once you have your project created, open NuGet and reference Catel.WP7 for a Windows Phone 7 app from the NuGet package manager window.
Next, let’s build a SensorViewModel, using Catel’s sensor services. We’ll start by declaring namespaces that Catel provides.
using Catel.Data;
using Catel.MVVM;
using Catel.MVVM.Services;
using Catel.MVVM.Services.Test;
using AccelerometerService = Catel.MVVM.Services.AccelerometerService;
using CompassService = Catel.MVVM.Services.CompassService;
using GyroscopeService = Catel.MVVM.Services.GyroscopeService;
using LocationService = Catel.MVVM.Services.LocationService;
Declare local variables for sensors services within for your view model:
private IAccelerometerService _accelerometerService;
private ICompassService _compassService;
private IGyroscopeService _gyroscopeService;
private ILocationService _locationService;
Sensor properties are exposed in the model similarly to this compass true heading sensor reading.
/// <summary>
/// Gets or sets the compass true heading.
/// </summary>
public double CompassTrueHeading
{
get { return GetValue<double>(CompassTrueHeadingProperty); }
set { SetValue(CompassTrueHeadingProperty, value); }
}
/// <summary>
/// Register the CompassTrueHeading property so it is known in the class.
/// </summary>
public static readonly PropertyData CompassTrueHeadingProperty = RegisterProperty("CompassTrueHeading", typeof(double));
You can include other sensors in your MVVM in a similar fashion. Services should be initialized before we can start collecting data:
protected override void OnNavigationCompleted()
{
bool testMode = bool.Parse(NavigationContext["testmode"]);
if (testMode)
{
InitializeTestSensors();
}
else
{
InitializeRealSensors();
}
_accelerometerService.CurrentValueChanged += OnAccelerometerValueChanged;
_compassService.CurrentValueChanged += OnCompassValueChanged;
_gyroscopeService.CurrentValueChanged += OnGyroscopeValueChanged;
_locationService.LocationChanged += OnLocationChanged;
if (_accelerometerService.IsSupported)
{
_accelerometerService.Start();
}
if (_compassService.IsSupported)
{
_compassService.Start();
}
if (_gyroscopeService.IsSupported)
{
_gyroscopeService.Start();
}
_locationService.Start();
}
And set values:
private void OnCompassValueChanged(object sender, CompassValueChangedEventArgs e) {
CompassMagneticHeading = e.Value.MagneticHeading;
CompassTrueHeading = e.Value.TrueHeading;
CompassHeadingAccuracy = e.Value.HeadingAccuracy;
}
Testing Sensor Data
Testing sensor data in Windows Phone 7 emulator is limited to accelerometer and location services. With Catel MVVM we are provided with the special test services that keep providing test data to the emulator! Instead of using the “real” sensor namespace, simply use the test one:
Initialize real sensors:
_accelerometerService = new AccelerometerService();
_compassService = new CompassService();
_gyroscopeService = new GyroscopeService();
_locationService = new LocationService();
Initialize test sensors:
_accelerometerService = new MVVM.Services.Test.AccelerometerService();
_compassService = new MVVM.Services.Test.CompassService();
_gyroscopeService = new MVVM.Services.Test.GyroscopeService();
_locationService = new MVVM.Services.Test.LocationService();
Sample Code
This code is available from https://catelexamples.codeplex.com/
Other MVVM Sensor links…
Kinect Sensor in an MVVM App (Source)
MVVM Light https://mvvmlight.codeplex.com
Caliburn https://caliburnmicro.codeplex.com