Over the past few years, I have found myself doing a lot of cross-platform development, in particular Silverlight for the browser, WPF, and now Windows Phone development. Being able to abstract common tasks away from technology specific types, such as displaying simple dialogs, has made reusing code far easier. In addition, mocking things, which would otherwise cause a unit test to fail on a build server, such as displaying a message box, has proven invaluable.
In several places throughout the book you see the use of an IMessageService
, which is used to display message dialogs to the user. The ViewModelBase
class exposes the IMessageService
as a MessageService
property, and you see calls like the following:
MessageService.ShowMessage("Hi from Windows Phone!");
If you are itching to sink your teeth into more phone-specific content, feel free to skip this section and return to it later.
The IMessageService
interface describes a class that is able to display messages to the user, and to ask the user questions (see Figure 2.11).
There are various parameters for specifying captions and so forth, along with the capability to provide a message importance threshold value, so that the user can nominate to have messages filtered based on importance.
Differences exist between the built-in dialog related enums in the MessageBox APIs of Windows Phone and WPF. Hence, these types have been replaced with the technology-agnostic enum types shown in Figure 2.11.
The Windows Phone implementation of the IMessageService
is done by extending a single class, the MessageServiceBase
class, and by overriding two abstract methods: one called ShowCustomDialog
, the other AskQuestion
(see Figure 2.12).
The ShowCustomDialog
method uses the Dispatcher
to display the dialog on the UI thread (see Listing 2.1). Extension methods are used to convert the native Silverlight MessageBoxButton
enum values and MessageBoxResult
enum values to the technology-agnostic enum values.
public partial class MessageService : MessageServiceBase
{
public override MessageResult ShowCustomDialog(
string message,
string caption,
MessageButton messageButton,
MessageImage messageImage,
MessageImportance? importanceThreshold,
string details)
{
/* If the importance threshold has been specified
* and it's less than the minimum level required (the filter level)
* then we don't show the message. */
if (importanceThreshold.HasValue
&& importanceThreshold.Value < MinumumImportance)
{
return MessageResult.Ok;
}
if (Deployment.Current.Dispatcher.CheckAccess())
{ /* We are on the UI thread,
and hence no need to invoke the call.*/
var messageBoxResult = MessageBox.Show(message, caption,
messageButton.TranslateToMessageBoxButton());
return messageBoxResult.TranslateToMessageBoxResult();
}
MessageResult result = MessageResult.Ok;
var context = new DispatcherSynchronizationContext(
Deployment.Current.Dispatcher);
context.Send(
delegate
{
var messageBoxResult = MessageBox.Show(
message, caption,
messageButton.TranslateToMessageBoxButton());
result = messageBoxResult.TranslateToMessageBoxResult();
}, null);
return result;
}
/* Content omitted. */
}
The downloadable sample code also contains a MockMessageService
class that inherits from MessageService
and is designed to be used for unit testing purposes. It allows you to verify that code correctly displayed a message or asked a question. The absence of a mocking framework for Windows Phone makes it especially useful.
The MessageService
can be used to display a message, or ask the user a question, from any viewmodel (see Figure 2.13).
You see how to use the IMessageService
in greater detail in the next chapter.
By using an interface based approach, it affords the opportunity to substitute the IMessageService
implementation for a mock implementation, or to even change the behavior of the IMessageService
entirely.
These classes are, of course, included in the downloadable sample code. Yet, they also reside in the CalciumSdk repository at http://calciumsdk.com, where you can always find the most up-to-date code, freely available for use in your projects.
18.227.134.154