In this post we are trying to focus how we can control application state for an App. We have chosen
Windows Store Apps as the platform of choice. It provides SimpleOrientationSensor as the device orientation changes.
Let's start with PCL
Let's create a simple Portable class library project. We are naming it as
SimpleOrientationEx.Portable. The project is supposed to hold the orientation state type. The application state would be based on an enumeration type, also defined in the same PCL project. For this simpleton project, let's use the maximum numbers of target frameworks.
These are the simple possible orientations of the app. It includes portrait, landscape and their contra-states. It also has face-up and face-down states. These are the states when the device is held in a perfect horizontal position either face-up or down. As a developer, you might have realized that it is really difficult for an app to determine how the device is being held, and should the display be using portrait or landscape layout.
Now let's introduce an interface type to hold the current application orientation. It holds the state in a
CurrentOrientation property. We are naming the interface-type as
IAppOrientation.
Let's implement this now. In addition to implementing the
CurrentOrientation member from the interface type, it also introduces a
protected member to update the current orientation of the App.
Windows Store App Orientation
As an example application, let us consider Windows Store Apps for Windows 8.1. We are creating a specialized type of
AppOrientationBase class to hold the orientation state of a Windows Store App. The specialized type is named as
AppOrientationWindowsStore.
Windows Store Apps can use
SimpleOrientationSensor to determine the device orientation. The sensor type is available in
Windows.Devices.Sensors namespace. It provides the application orientation using enumeration type.
The enumeration type has similar values as our
AppOrientationState. We can define a mapping between the enumeration values of
AppOrientationState and
SimpleOrientation. Here
MapOrientation() method is defining this mapping for us.
Let's introduce Reactive Extensions
Here we are adding
reactive extensions core nuget package [
Reactive Extensions Homepage]. Not only this makes
throttling these events a child's play but also provides the events as
Obervable.OnNext() sequence. This can be achieved using Obervable.FromEventPattern().
Since updating the layout for orientation change can be very involved process rendering heavy load elements, let us throttle the orientation changes a little. Here we are
throttling the OrientationChanged event from
SimpleOrientationSensor for one second. The throttled events are not raised in the publisher's thread but a different thread pool thread. Since we are updating the UI in the subscription code, we can observe the sequence using
SynchronizationContext.Current. This would execute the handler code in the required UI thread.
Prism for Windows Store App
Now let us add
Prism for Windows Store App nuget package. We introduce the main view model for the App. It just has a string based property to hold some text data. The view model inherits from
ViewModel type from Prism.
The view model keeps the App orientation. It instantiate the member using default SimpleOrientationSensor. Like other Windows Store App sensors,
SimpleOrienationSensor singleton instance can be obtained using the static
GetDefault() method.
Prism for Windows Store App provides the support of restoring the application state using
RestorableState attribute. We are decorating the only property with this attribute. This should restore the application state when application is restored to
Running from
Suspended state. [MSDN:
App Lifecycle] [
Handling Suspend, Resume & Activation in a Windows Store App]
Prism for Windows Store App also provides
MvvmAppBase type. We can inherit from this to further control the App. Here we are overriding
OnLaunchApplication and
OnNavigationFailed methods. Here OnLaunchApplication is being used to navigate to
MainPage.xaml as the app is launched. Based on the convention, we must have
[X]Page.xaml. Here [X] is the first argument to the
NavigationService.Navigate() method. We can override this mapping by overriding
GetPageType() method. It is passed with the same string as
pageToken and it should return the mapped
Page type.
Now we add an
IValueConverter to convert the enumeration value to string.
App Orientation and View Updates
Now we turn our attention to the view. We have a simple view with a
TextBlock and
TextBox. They are bound to the same property in the view model. Here we are using Prism's view model auto-wiring capabilities. The view model should be named following the Prism's convention. For our case, it is named as
MainPageViewModel [
[X]PageViewModel ].
Here we have also introduce a
RotateTransform for the Grid to the
RenderTransform property. We are defining the center of the grid as the origin of the transformation by assigning
RenderTransformOrigin as
"0.5, 0.5".
Now we add
Visual states to the page. All of these states correspond to different states in
AppOrientationState enumeration. In order to keep the example simple, we are just animating the RotateTransform defined above for the Grid. It just rotates it keeping the view always upright. We are also defining transitions to these states to ease the rotation effect.
Introduce Behavior SDK (XAML) extension
Now we need to define the transitions between these states. These transitions should be based on the states in
IAppOrientationState in
MainPageViewModel. This is very tricky in Windows Store Apps as there is
no DataTrigger support for the platform. In Visual Studio 2013, Microsoft added support for some behaviors including
DataTriggerBehavior. Let us add the extension SDK using Reference Manager dialog.
In addition to
DataTriggerBehavior, we are also using
GotToStateAction from the same extension. This can be used to transition to a particular visual state.
Get Code from GitHub