WP7 – Testable Touch with MVVM

I have been working on my second application for the last two weeks and wanted to share some code.  As stated before, I’m really enjoying the MVVM pattern and how it makes code more testable.  I wasn’t sure that I would be able to test touch interaction with the phone but was able to work it out.

Windows Phone 7 has the same touch hooks as Silverlight 3, as far as I can tell.  You simply, add an event handler for the Touch.FrameReported event in the constructor of your page code-behind.

public myPage()
{
InitializeComponent();

Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
}

private void Touch_FrameReported(object sender, TouchFrameEventArgs e) { … }

The TouchFrameEventArgs gives you all the current touch points uniquely identified by id (in order of touch) along with their position, size and action (up, down or move).

I used the MVVM Light Messenger to pass this info along to my ViewModel but first I had to convert the touch points from the closed System.Windows.Input.TouchPoint and System.Windows.TouchDevice classes to my own open classes.  These system classes are not easily instantiated which makes testing much more difficult.  My classes mimic the others in name and structure but allow setting of any properties.

private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
IList<OpenTouchPoint> points = e.GetTouchPoints(null).Select(tp => new OpenTouchPoint(tp)).ToList();

Messenger.Default.Send(new NotificationMessage<IList<OpenTouchPoint>>(points, string.Empty));

}

I register this message in my ViewModel and assign an action to it.  I’m using a dictionary of actions by TouchAction type (up, down, move).

Messenger.Default.Register<NotificationMessage<IList<OpenTouchPoint>>>(this, message =>
message.Content.ForEach(touchPoint => _touchActions[touchPoint.Action](this, touchPoint)));

To test this I simply send a message from my unit test and then assert on the ViewModel properties.

_testTouchPoints = new List<OpenTouchPoint>
{
new OpenTouchPoint {Action = TouchAction.Move, TouchDevice = _touchDevice, Position = _newPoint}
};

Messenger.Default.Send(new NotificationMessage<IList<OpenTouchPoint>>(_testTouchPoints, string.Empty));

I was a little worried that all this code for getting touch points would slow down performance but I am getting and using four simultaneous touch points with very little lag.  WP7 supports up to 10 touch points.  I’ll be interested to see how it performs with ten at a time.

Leave a Reply