Contents
PART 1 : StyleMVVM Fundamentals (this article)
PART 2 : StyleMVVM Demo App Walkthrough
Introduction
About a year ago I contacted by this uber sharp American guy called Ian Johnson, who asked me if I would be so kind as to review his upcoming Windows 8 MVVM library.
I stated that I was currently on holiday, but when I got back I would be glad to. Now I have been in pretty much constant contact with Ian over the past year and have been fielding his questions, and we have even written a joint
article (Expression API Cookbook).
What immediately struck me about Ians framework (here after known as StyleMVVM) was how feature rich it was, and how well thought out it all was. Remember I have taken time to look at his code base.
At the time I was lucky enough to be asked to be an advisory member for the new PRISM offering for Windows 8 code name "Kona". I didn't really have enough time to do much on this but it was still an honor. Though I have since spent quite a bit of time getting to known "Kona" now known as "PRISM for Windows Runtime".
Now I love PRISM and have nothing but respect for that team, and previous team members, but I have to also say at the moment, I prefer the StyleMVVM offering, as I think it is just more feature rich, and some of the code seems to be better to use than PRISM for Windows Runtime.
One thing I really liked in StyleMVVM was the fact that Ian had written a Expression Tree (fast as hell) IOC container from scratch. He has bench marked this and it is
right up there, with speeds far exceeding Castle / Unity and AutoFac. It is based around the MEF style attribute model, but fluent registration is also happening any second now (I know I have seen the beta versions of it, and it looks very cool). Ian is very proud of this piece of StyleMVVM , and rightly so, its awesome.
Now that is no small thing, for a single individual to come up with a framework as feature rich as one of the big boys in the MVVM arena, kudos to Ian.
I believed in Ians work so much I have been working on a demo app using it in my spare time. This demo app will be the source for
the next article in this series of articles.
In this article we will concentrate on some of the features of StyleMVVM.
Prerequisites
If you just want to read this article as an introduction to StyleMVVM,
then you don't need anything. If you like what you read and you want to take StyleMVVM
for a spin, you will need
- Visual Studio 2012 / 2013
- Windows 8 / 8.1
If you like what you have read even more, and decide to take the attached
demo code (that is my demo not the one that comes with the StyleMVVM
source code), you will additionally need to install the following:
- SQLite Windows 8 stuff:
http://sqlite.org/2013/sqlite-winrt80-3080002.vsix (though that is
included in the demo code download you just need to run it. It is a Visual
Studio Extension so just double click it)
- Once you have done step 1 here, ensure that the NuGet packages are all
present, and if they aren't restore them. And also ensure that you have
references the installed (from step 1) SQLite library
What Does StyleMVVM Provide Out Of The Box?
As I have already stated StyleMVVM
is extremely feature rich, and as such provides a great many (and Ian is very
open to adding new stuff, I know because I have asked him to add stuff for me, which
he did straight away) services/helpers that one would expect from any awesome
MVVM framework.
A list of some of the core StyleMVVM
features which I have shamelessly stolen from the StyleMVVM codeplex
site is shown below:
- StyleMVVM is the only MVVM toolkit for Window Store App that supports all three development languages C#, C++/CX and HTML/JS. Allowing you to export components written in C++/CX and import them into a C# applications.
- Built-in validation engine that supports ValidationAttributes, Fluent validation and Method validation depending on your needs. You can validate ViewModels as well as DataModels.
- Conventions module to allow for easier development, as well as templates to setup your project to use conventions.
- Event Handlers can be easily hooked up to your view model using the simple syntax
View:EventHandler.Attach="EventName => ViewModelMethod($sender,$eventArgs);
etc..." - Supports Regions similarly to Prism with region registration happening in XAML and navigation being driven from the ViewModel
- Attribute Based IoC container (Export, Import), container is also environment aware and sorts exports accordingly returning the best match at Locate time (RunTime, DesignTime, UnitTest).
- Fluent interfaces for configuring IoC Container programmatically (required for C++/CX and Windows Runtime Components)
- Design time ViewModel support. ViewModels are located at design time using IOC so you can use your real ViewModel and replace your
IDataService
with a Faux version for Design and UnitTest. - Auto Registration of Views and WCF Clients (i.e., all classes inheriting from
ClientBase<T> & Page
) - Implementations for
ICommand
and Attached Event Commands. - Messenger service that is Dispatcher Aware (i.e., handlers are called back on the proper dispatcher)
NavigationViewModel
that is tied into the Metro Page Navigation system (Supporting Navigate method
and Navigation Events) - Extensible logging solution
- Configuration service that is expandable by Exporting the
IConfigurationStorageProvider
interface - Improved Suspension Manager (auto adds DataContract classes to KnownTypes)
IMessageBoxService
and IFilePickerService
wrappers that allow you to mock out your dialogs for Design and Unit Testing purposes ICharmService
makes creating fly-out easy by automatically registering charm controls with the SettingPane. ITileService
, IBadgeService
, and IToastService
allow for easy updates of tiles and toasts. IActivationService
that can create or clone any Object (satisfying Imports and message registration) ITransformService
can transform data objects from one type to another using reflection and LINQ Expressions, you can use the
Transform
attribute to give the service hints on how to transform the property. - Visual Studio Template for Projects and Items
A Deeper Dive Into Using StyleMVVM
In this section we will dive into how you can use StyleMVVM
to develop your own applications.
Typical Boostrapper Code
I have to say I am not a massive fan of the whole WinRT app file. I think it
is
a bloody mess truth be told. That said it is what it is, and as such we must
work with it. To kick start StyleMVVM
we need to apply a BootStrapper (just like we did in PRISM). Shown
below is a typical App.xaml.cs file that one might use when using StyleMVVM:
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
CreateBootstrapper();
}
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
LaunchBootStrapper();
if (args.PreviousExecutionState == ApplicationExecutionState.Running)
{
Window.Current.Activate();
return;
}
var rootFrame = new Frame();
StyleMVVM.Suspension.SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
await StyleMVVM.Suspension.SuspensionManager.RestoreAsync();
}
if (rootFrame.Content == null)
{
Type navigateType = Bootstrapper.Instance.Container.LocateExportType("StartPage");
if (navigateType == null)
{
throw new Exception("Could not find start page.");
}
if (!rootFrame.Navigate(navigateType))
{
throw new Exception("Failed to create initial page");
}
}
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await StyleMVVM.Suspension.SuspensionManager.SaveAsync();
deferral.Complete();
}
private void CreateBootstrapper()
{
if (!Bootstrapper.HasInstance)
{
Bootstrapper newBootstrapper = new Bootstrapper();
newBootstrapper.Container.RegisterAssembly(
GetType().GetTypeInfo().Assembly);
newBootstrapper.Container.RegisterAssembly(
typeof(CSharpContainerLoader).GetTypeInfo().Assembly);
newBootstrapper.Start(false);
}
}
private void LaunchBootStrapper()
{
Bootstrapper.Instance.Launched();
}
}
As I say I think the amount of code that has to be placed in this file is dreadful, a bad
separation of concern, and a total abortion frankly. This is nothing
to do with Ian or StyleMVVM,
it is the WinRT way. Cool huh?
IOC Usage
What Ian has done within StyleMVVM
is to go for a MEF type of approach where you use certain attributes to indicate
what you want Export
ed and how.
There is a fluent interface coming (which I am glad to say I had some part
in), that will be coming very soon.
For now, let's look at a table of how you might do certain things:
Task | What Do I Do |
Export something to the container |
[^__strong__^Export]
public class ScheduleViewModel
|
Mark something as a Singleton |
[Singleton]
[Export(typeof(ISqlLiteDatabaseService))]
public class SqlLiteDatabaseService : ISqlLiteDatabaseService |
Export as a specific Type |
[Singleton]
[Export(typeof(ISqlLiteDatabaseService))]
public class SqlLiteDatabaseService : ISqlLiteDatabaseService |
Import stuff in the constructor |
[ImportConstructor]
public MainPageViewModel(IEnumerable<ipageinfo> pageInfos)
{
}</ipageinfo> |
Run a particular View as the start View for the
app |
[StartPage]
public sealed partial class MainPage : LayoutAwarePage
{
} |
You can expect to see more around the container in future releases of StyleMVVM.
Base ViewModels
StyleMVVM
includes a number of handy base class ViewModels that you may like to
inherit from.
Here is a list of them:
PageViewModel
- Base class to use for ViewModels that might go with a
Page
type view. This also provides these extra helper methods:
public INavigationService Navigation { get; }
public FrameworkElement View { get; set; }
-
public virtual void OnLoaded(object sender,
RoutedEventArgs args);
-
public virtual void OnUnloaded(object sender,
RoutedEventArgs args);
NavigatingViewModel
- Base class to use for ViewModels that might go with a navigation
aware type view. This also provided these extra helper methods:
-
protected virtual Task InternalNavigatingFrom(object
sender, StyleNavigatingCancelEventArgs e);
-
public void NavigatedFrom(object sender,
StyleNavigationEventArgs e);
-
public void NavigatedTo(object sender,
StyleNavigationEventArgs e);
-
public IAsyncAction NavigatingFrom(object sender,
StyleNavigatingCancelEventArgs e);
-
protected virtual void OnNavigatedFrom(object sender,
StyleNavigationEventArgs e);
-
protected virtual void OnNavigatedTo(object sender,
StyleNavigationEventArgs e);
-
protected virtual Task OnNavigatingFrom(object sender,
StyleNavigatingCancelEventArgs e);
BaseViewModel
- Simple container aware INPC viewmodel
These base classes are invaluable in my opinion, and tackle some of the
really tricky stuff when dealing with MVVM, such as these:
- When my my page loads I want to run some method. Ok so simply override
the
OnLoaded(..)
method in PageViewModel
- I need to get the navigation parameters. Ok so simply override the
NavigatedTo(..)
method in NavigatingViewModel
Those that have used PRISM will certainly, seems some similarities.
PageViewModel
Now that we have discussed some of the bases classes provided by StyleMVVM,
I just want to look at one of them in detail, which is the PageViewModel
:
When you use the StyleMVVM
PageViewModel
you can do neat things like
- Interact with the View as a
Framework
element, which means
you can get its Dispatcher
- Do things when the View loads/unloads
- Override the
OnNavigatedTo(..)
and use the
StyleNavigationEventArgs
to grab the navigation context
parameters
Navigation
If you inherit from PageViewModel
you will get access to the
Navigation
property (which gives you the INavigationService
), which you can use
to navigate quite simply as follows:
string state = "Sending state";
Navigation.Navigate("SomeView",state);
Then within the page (providing you inherited from PageViewModel
you can grab out the
Navigation
context data via the use of the OnNavigatedTo(..)
and use the
StyleNavigationEventArgs
View / ViewModel WireUp
StyleMVVM
supports wiring up a View to its ViewModel via an attached DependencyProperty
(much like I used to do with my own
Cinch framework), here is how it is done.
In the View you simply need to do this:
<Common:LayoutAwarePage
x:Class="Demo.Views.SomePage"
....
xmlns:View="using:StyleMVVM.View"
View:ViewModel.Name="SomePageViewModel">
...
...
...
</Common:LayoutAwarePage>
And in the Views code behind you need to do this. This step is mandatory, without this setup the View will
not be able to resolve its ViewModel.
[Export]
public sealed partial class SomePage : LayoutAwarePage
{
public MainPage()
{
this.InitializeComponent();
}
}
Where your ViewModel might look like this:
public class SomePageViewModel : PageViewModel
{
}
Validation
StyleMVVM
comes with several different flavors of validation out of the box, it is pretty
much up to you which of these you go for. Before we look at each of the
different types of validation within StyleMVVM
lets just come up with a simple ViewModel that the examples below will all work
against to perform their validation.
public class BasicValidationViewModel : PageViewModel, IValidationStateChangedHandler
{
private string prefix;
private string firstName;
private string lastName;
private string middleName;
private string emailAddress;
private DelegateCommand saveCommand;
public DelegateCommand SaveCommand
{
get
{
if (saveCommand == null)
{
saveCommand = new DelegateCommand(SaveMethod,
x => ValidationContext.State == ValidationState.Valid);
}
return saveCommand;
}
}
public IEnumerable<string> Prefixes
{
get { return new []{ "Mr","Mrs","Ms","MD","Phd"};}
}
[Required]
public string Prefix
{
get { return prefix; }
set { SetProperty(ref prefix, value); }
}
[Required]
public string FirstName
{
get { return firstName; }
set { SetProperty(ref firstName, value); }
}
[Required]
public string LastName
{
get { return lastName; }
set { SetProperty(ref lastName, value); }
}
[Required]
public string EmailAddress
{
get { return emailAddress; }
set { SetProperty(ref emailAddress, value); }
}
public string MiddleName
{
get { return middleName; }
set { SetProperty(ref middleName, value); }
}
[Import]
public IValidationContext ValidationContext { get; private set; }
[Import]
public IMessageBoxService MessageBox { get; set; }
[ActivationComplete]
public void Activated()
{
ValidationContext.RegisterValidationStateChangedHandler(this);
}
private void SaveMethod(object parameter)
{
MessageBox.Show("Save Clicked");
}
public void StateChanged(IValidationContext context, ValidationState validationState)
{
SaveCommand.RaiseCanExecuteChanged();
}
}
A couple of salient points in this example ViewModel:
- It can be seen that you free to use the
System.ComponentModel.DataAnnotations
namespace attributes, such as
RequiredAttribute
.
StyleMVVM
will work just fine with the
System.ComponentModel.DataAnnotations
namespace attributes. - That you should make sure that the
IValidationContext
is
marked as an [Import]
property. This can not come via
constructor injection, as we need the target object to be created prior to
the IValidationContext
being created. So it must
be a property [Import]
- That we hook up the
IValidationContext
in the
Activated
method (see the [ActivationComplete]
usage)
which we can then use to disable ICommand
objects based on the
current objects valid/invalid state. Have a look at the constructor above
you will see what I mean
Fluent Validation Framework
StyleMVVM
comes with an inbuilt fluent API for configuring the validation. here is a small
example based on the example ViewModel above.
[Export(typeof(IFluentRuleProvider<BasicValidationViewModel>))]
public class FluentValidationForBVVM : IFluentRuleProvider<BasicValidationViewModel>
{
public void ProvideRules(IFluentRuleCollection<BasicValidationViewModel> collection)
{
collection.AddRule("MiddleNameRule")
.Property(x => x.MiddleName)
.IsRequired()
.When.Property(x => x.FirstName)
.IsNotEmpty();
}
}
By inherited from IFluentRuleProvider<T>
and exporting it
via the [ExportAttribute]
StyleMVVM
will make sure the ViewModel that the Fluent rules have been created for get
setup correctly for you. I think the best way to get to grips with the StyleMVVM
fluent validation API is to have a play with it.
Method Type Validation
You can also create a custom method validation where you can run any logic
you want. As before here is an example for the ViewModel just shown above:
[Export(typeof(IValidationMethodProvider<BasicValidationViewModel>))]
public class MethodValidationForBVVM : IValidationMethodProvider<BasicValidationViewModel>
{
public void ProvideRules(IValidationMethodCollection<BasicValidationViewModel> methodCollection)
{
methodCollection.AddRule(IanJohnsonRule).
MonitorProperty(x => x.FirstName).MonitorProperty(x => x.LastName).MonitorProperty(x => x.MiddleName);
}
private void IanJohnsonRule(IRuleExecutionContext<BasicValidationViewModel> obj)
{
if (string.Compare(obj.ValidationObject.FirstName, "Ian",
StringComparison.CurrentCultureIgnoreCase) == 0 &&
string.Compare(obj.ValidationObject.MiddleName,
"Phillip", StringComparison.CurrentCultureIgnoreCase) == 0 &&
string.Compare(obj.ValidationObject.LastName,
"Johnson", StringComparison.CurrentCultureIgnoreCase) == 0)
{
obj.AddError(x => x.FirstName, "Your first name can't be Ian when your last name is Johnson");
obj.AddError(x => x.MiddleName,"Your middle name can't be Ian Phillip Johnson ... I am!");
obj.AddError(x => x.LastName, "Your first name can't be Ian when your last name is Johnson");
obj.Message = "You can not be Ian Phillip Johnson ... Identity Thief!";
}
}
}
By inherited from IValidationMethodProvider<T>
and exporting it
via the [ExportAttribute]
StyleMVVM
will make sure the ViewModel that the rules the method provides have get setup
correctly for you. As before, the best way to deal with this is have a play.
Validation Control Templates And Styles
Sadly and quite strangely, there does not seem to be any standard validation
Styles/ControlTemplates supplied out of the box for Windows 8/WinRT. Luckily Ian
has rectified this by providing some within the StyleMVVM
source code. You just need to look for the following
ResourceDictionary
in the downloaded
StyleMVVM
source code:
Release-XXXX\Examples\ExampleApp\ExampleApp\Common\FrameworkStyles.xaml
And you should see that, that ResourceDictionary
contains a few
useful validation Styles/ControlTemplates that can be used with StyleMVVM,
such as:
- ValidationTextbox
- ValidationComboBox
These can then be applied like this in the XAML:
<UserControl
x:Class="ExampleApp.Views.Validation.BasicValidationView"
.....
xmlns:View="using:StyleMVVM.View"
View:ViewModel.Name="BasicValidationViewModel">
<Grid>
<ComboBox Template="{StaticResource ValidationComboBox}"
SelectedItem="{Binding Prefix,Mode=TwoWay}"
View:Validation.Property="Prefix"
ItemsSource="{Binding Prefixes}"/>
<TextBox Text="{Binding FirstName,Mode=TwoWay}"
View:Validation.Property="FirstName"
Template="{StaticResource ValidationTextbox}"/>
</Grid>
</UserControl>
Also note how we pick out what property we would like to use for the
validation filter. When run this would produce something like this:
The good thing about how StyleMVVM
does its validation is that every type of control can potentially show
validation errors. You just need to create the correct Style/ControlTemplate. As
I say Ian has created the 2 listed above, but if you find you need more just
borrow ideas from the TextBox
one (ValidationTextBox
) and
ComboBox
(ValidationComboBox
) one that Ian has already crafted for you.
Restorable ViewModels
Windows 8 follows the same type of lifecycle as Windows Phone, where an app
can go through various lifecycles, including suspension. Windows 8 comes
with a standard SuspensionManager
. However to make things simple StyleMVVM
comes with its own, SuspensionManager
which we saw wired up in the
App.xaml.cs
code we looked at earlier.
Now to make things uber simper StyleMVVM
provides two attributes (SyncableAttribute
and
SyncAttribute
shown below) you can use to ensure your ViewModel state gets stored on
suspension and restored correctly on re-activation.
Here is an example of a small ViewModel that uses these two StyleMVVM
attributes:
[Export]
[Syncable]
public class ScheduleViewModel : BaseViewModel
{
[Sync]
public bool HasItems
{
get { return hasItems; }
set { SetProperty(ref hasItems, value); }
}
}
And that is all you need to do. StyleMVVM
takes care of things for you by using the DataContractSerializer
behind the
scenes. Good stuff I say.
DelegateCommand
An oldy but a goody, the by now famous DelegateCommand
(these days I tend to
use a more Rx based ICommand
, for those interested you can read more here :
http://sachabarbs.wordpress.com/2013/10/18/reactive-command-with-dynamic-predicates/)
However back to the subject at hand, here is StyleMVVM
DelegateCommand
, which you can use to run command logic directly in your
ViewModel. Though again I recommend a separate controller, or maybe even many
micro controllers to get your ViewModel nice and lean.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StyleMVVM.ViewModel
{
public delegate void DelegateAction(object parameter);
public delegate bool DelegateCanExecute(object parameter);
public sealed class DelegateCommand : ICommand
{
private readonly DelegateAction command;
private readonly DelegateCanExecute canExecute;
public DelegateCommand(DelegateAction command)
{
this.command = command;
}
public DelegateCommand(DelegateAction command, DelegateCanExecute canExecute)
{
this.command = command;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (canExecute != null)
{
return canExecute(parameter);
}
return true;
}
public void Execute(object parameter)
{
command(parameter);
}
public void RaiseCanExecuteChanged()
{
if (InternalCanExecuteChanged != null)
{
InternalCanExecuteChanged(this, EventArgs.Empty);
}
}
event EventHandler ICommand.CanExecuteChanged
{
add { InternalCanExecuteChanged += value; }
remove { InternalCanExecuteChanged -= value; }
}
internal EventHandler InternalCanExecuteChanged;
}
}
Which you can use like this (say):
CaptureImageCommand = new DelegateCommand(ExecuteCaptureImageCommand,
x => ValidationContext.State == ValidationState.Valid);
Event To Command / Method
Now one thing to note with WinRT development. Out of the box you can't fall
back to the old tricks you used with WPF/SL where you used the
Blend.Interactivity DLLs. They don't work.
There is a CodePlex offering
http://winrttriggers.codeplex.com/
should you want to use it. For this article I will stick to what StyleMVVM
offers, for one of the most common interactivity scenarios. The
Event to Command scenario, which again is pretty standard in most
MVVM frameworks out there.
Here is how StyleMVVM
does it.
In the XAML you would do this:
<ListView View:EventHandlers.Attach="ItemClick => ItemClicked($sender,$eventArgs)" />
And in your ViewModel you would do this:
public void ItemClicked(FrameworkElement element,ItemClickEventArgs eventArgs)
{
MessageBoxService.Show("You clicked: " + eventArgs.ClickedItem);
}
Core Services
This section outlines some of the core services supplied by StyleMVVM. I will not cover every single one of them in this article (as there just is not enough time
in the day for that). You can however see the example application that comes with StyleMVVM. This example is located within the source code at a path something like:
Release-3.0.3\Examples\ExampleApp
Messager / Mediator
Any MVVM worth its salt will have a weak event messaging component, whether
that is an internal Rx stream based approach (this is what I use these days) or
a standard weak event handling mediator, they should all still have one. StyleMVVM
as you would expect, has one. Ian calls his IDispatchedMessager
(see how it works with JavaScript too) which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
namespace StyleMVVM.Messenger
{
public delegate void JSCallback(object message);
public interface IDispatchedMessenger
{
void Send(object message);
void Register(object callback);
void Register(object callback, bool background, bool holdReference);
void RegisterMethod(object target, string methodName, bool background, bool holdReference);
void RegisterJSCallback(TypeWrapper messageType, JSCallback callback, bool background);
void Unregister(object callback);
void RegisterObjectHandlers(object handlerObject);
void UnregisterObjectHandlers(object handlerObject);
}
}
This is how you might publish something out on the IDispatchedMessager
, which is a singleton by the way
DispatchedMessenger.Instance.Send(new TextMessage {Text = TextMessage});
And this is how you might subscribe to a particular message on the IDispatchedMessager
[MessageHandler]
public void TextMessageHandler(TextMessage message)
{
TextMessage = message.Text;
}
Note: Messages subscription is weak by default.
IMessageBoxService
This is a simple MessageDialog wrapper. Once you see the interface exposed
via the service its should make total sense how to use it. Here is the exposed
interface:
using System.Collections.Generic;
using System.Threading.Tasks;
#if !DOT_NET
using Windows.Foundation;
#endif
#if !NETFX_CORE
using System.Windows;
#endif
namespace StyleMVVM.View
{
public interface IMessageBoxService
{
void Notify(string message);
void Notify(string message, string title);
#if NETFX_CORE
void Notify(string message, string title, string buttonText);
IAsyncOperation<string> Show(string message);
IAsyncOperation<string> Show(string message, string title, params string[] commands);
IMessageDialog MessageDialog(string message, string title);
IAsyncOperation<SystemMessageBoxResult> ShowSystemMessageBox(string message);
IAsyncOperation<SystemMessageBoxResult> ShowSystemMessageBox(
string message, string title, SystemMessageBoxButton button);
#else
Task<string> Show(string message);
#if DOT_NET
void Notify(string message, string title, string buttonText);
Task<string> Show(string message, string title, params string[] commands);
Task<MessageBoxCommand> Show(string message,
string title,
MessageBoxCommand command,
params MessageBoxCommand[] commands);
Task<MessageBoxCommand> Show(string message, string title, IEnumerable<MessageBoxCommand> commands);
#endif
Task<SystemMessageBoxResult> ShowSystemMessageBox(string message);
Task<SystemMessageBoxResult> ShowSystemMessageBox(string message,
string title, SystemMessageBoxButton button);
#endif
}
}
Based on that, we can simply do this
var result = await messageBoxService.Show("There was a problem save the Patient data");
IFilePickerService
This is a simple OpenFileDialog
/ SaveFileDialog
wrapper. Once you see the interface exposed
via the service its should make total sense how to use it. Here is the exposed
interface:
using System.Collections.Generic;
using System.Threading.Tasks;
using StyleMVVM.Utilities;
#if !DOT_NET
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.Pickers;
#endif
namespace StyleMVVM.View
{
public interface IFilePickerService
{
#if NETFX_CORE
IAsyncOperation<IReadOnlyList<StorageFile>> PickMultipleFilesAsync(
PickerLocationId location, params string[] filterTypes);
IAsyncOperation<StorageFile> PickFileAsync(PickerLocationId location, params string[] filterTypes);
#elif WINDOWS_PHONE
Task<IReadOnlyList<StorageFile>> PickMultipleFilesAsync(
PickerLocationId location, params string[] filterTypes);
Task<StorageFile> PickFileAsync(PickerLocationId location, params string[] filterTypes);
#elif DOT_NET
Task<IReadOnlyList<string>> PickMultipleFilesAsync(
PickerLocationId location, params string[] filterTypes);
Task<string> PickFileAsync(PickerLocationId location, params string[] filterTypes);
Task<string> PickSaveFileAsync(PickerLocationId location, params string[] filterTypes);
#endif
}
}
Based on that, we can simply do this
StorageFile storageFile = await FilePicker.PickFileAsync(PickerLocationId.DocumentsLibrary, ".txt");
ICharmService
This is the service that controls the creation of the settings pane and
activates charms. I will not be covering this within this article see the StyleMVVM
example:
ITileService
This interface provides a wrapper around TileUpdater as well as providing an
easy way to generate Tile updates. I will not be covering this within this
article see the StyleMVVM
example.
IBadgeService
Service wrapper around the badge functionality. I will not be covering this
within this article see the StyleMVVM
example.
Represents a service that allows you to create Toast Notifications. I will
not be covering this within this article see the StyleMVVM
example.
ITransformService
This service offers a code free way to transform from one type to another
type. This could be useful when going from ViewModel to Model and vice versa. I
will not be covering this within this article see the StyleMVVM
example.
That's It
Anyway that is all I wanted to say this time. I am sure you will agree that
Ian has done a rather splendid job on StyleMVVM,
and that using this awesome framework kind of makes up for the complete PITA that
Windows 8 is right now. If it had not have been for StyleMVVM
I would have gone completely nuts working with WinRT in its current state, it
was only saved by the fact that Ians code just worked and did exactly what I
wanted out of the box. And when it didn't I told him and he added it, top
fellow.
Next time we will be looking at
a demo app that I put together using StyleMVVM,
which uses most of the stuff outlined above, as well as interacting with a
camera, it also makes use of the search contract, and uses a small
SQLite database such that the demo app is more real world like.
Hopefully I will manage to write that up pretty soon. If you just can't wait
to look at it, you can grab the demo app for the next article at the top of this
article. Here is a brief overview of what the demo app for the next article
does:
- Page to capture patient details (Expects to capture an image for the
patient here too)
- Create appointments against a list of known doctors
- View appointments for a given day
- Drill in to a specific doctors appointments
- Show some statistics for a given day (simple pie chart of how many
appointments are scheduled against each doctor for a given day)
- Search contract has been implemented, such that you can search the demo
app right from the SearchPane in Windows 8
As always any votes/comments are welcome, and I am sure Ian would appreciate
people taking his baby (StyleMVVM
of course) for a spin.