Friday, 28 June 2013

Prism Presentations at TechEd Europe

Brian Noyes has delivered a presentation at TechEd Europe on using Prism for the Windows Runtime to build Windows Store business apps.

He’s also delivered another presentation on mastering navigation in Windows Store apps, also by using Prism for the Windows Runtime.

They are both worth a watch if you want to get a good grounding in how to use Prism for the Windows Runtime.

Testing your C#-based Windows Store App: Top 10 areas to look for bugs

Francis Cheung, the lead-dev of Prism for the Windows Runtime, has given a talk at Build 2013 on the top 10 areas to look for bugs when writing a Windows Store app.

The top 10 problem areas are:

  • Suspend/resume
  • Terminate/restart
  • Client updates
  • Network connectivity
  • Asynchronous code
  • Resolutions and orientation
  • Device testing
  • Localizability
  • Accessibility
  • Review against user experience (UX) guidelines.

These were derived by harvesting the knowledge gained while working on the AdventureWorks Shopper app, and Prism for the Windows Runtime.

Monday, 24 June 2013

Suspend/resume/activation using Prism for the Windows Runtime

Previously I extended the sample photo viewing app so that the user can covert a colour photo to greyscale, on the PhotoPage. This used MVVM and commands to bind the Command property of a Checkbox control to a DelegateCommand property on the PhotoPageViewModel. When the control’s command is invoked, the code in the view model is executed.

In this blog post I’ll further extend the app so that page state can be serialized during suspension, and de-serialized when the app reactivates. Specifically, the IsGreyscale property of the PhotoPageViewModel class will be serialized/de-serialized so that when the app reactivates following termination, the state of the Checkbox control will be identical to when the app was suspended. Prism for the Windows Runtime makes performing this task very straight forward.

Implementation

Suspend

To have data survive the suspend/terminate cycle with Prism all you have to do is mark any properties whose data you want to survive termination with the custom [RestorableState] attribute.

[RestorableState]
public bool IsGreyscale { get; set; }

When the the page is navigated away from the data contained in any properties marked with the custom [RestorableState] attribute is serialized to disk. All this work is performed by the Prism.StoreApps library. For details of how Prism undertakes this operation see Handling suspend, resume, and activation in AdventureWorks Shopper.

Resume

When an app resumes from suspension it continues from where it was when it was suspended, as the app is still stored in memory. Therefore, the sample app has no special behaviour associated with resuming from suspension. However, other apps may need to refresh content from network connections, the file system etc. For more information see Developing an end-to-end Windows Store app using C++ and XAML: Hilo.

Activation

Windows may terminate an app after it has been suspended, if the system is low on resources. When a Prism app is reactivated, any properties that are marked with the custom [RestorableState] attribute, such as the IsGreyscale property in the sample app, will have their values restored from disk. All this work is performed by the Prism.StoreApps library. For details of how Prism undertakes this operation see Handling suspend, resume, and activation in AdventureWorks Shopper.

To ensure that a greyscale photo is shown on reactivation, provided that the IsGreyscale property is true, the OnNavigatedTo method in the PhotoPageViewModel class calls the ConvertPhotoToGreyscale method.

if (IsGreyscale)
{
    ConvertPhotoToGreyscale();
}

The overall effect of this is that if the user had the greyscale Checkbox control checked when the app suspended/terminated, the Checkbox control will be checked when the app reactivates, thus ensuring that the photo is displayed as greyscale rather than colour.

Summary

In this blog post I’ve further extended the sample PhotoViewer app so that along with frame state, page state can be serialized during suspension and de-serialized when the app reactivates following termination. This is achieved by marking properties whose values you want to survive termination with the custom [RestorableState] attribute.

The sample app can be downloaded here.

Thursday, 20 June 2013

Prism for the Windows Runtime Templates Updated

I’ve updated the Prism for the Windows Runtime templates on the Visual Studio gallery. v1.1 of the templates introduce:

  1. Support for any edition of Visual Studio 2012 that you can create Windows Store apps with, starting from Visual Studio Express 2012 for Windows 8.
  2. A Flyout View Model item template that can be used to create Flyout view models for Prism apps.

For more info and to download the templates see Prism Templates.

Monday, 17 June 2013

Accessing Image Pixel Data in a C# Windows Store App

Previously I’ve written about how to access image pixel data in a C++/CX Windows Store App. Depending on your app, you may have a requirement to perform imaging operations that manipulate the pixel values of an image. Rather than have an Image control display a BitmapImage, I’ve modified my PhotoViewer sample app to display a WriteableBitmap instead, allowing the manipulation of an image at the pixel level. This should be a useful blog post as many of the posts concerning this topic on the forums are not optimal.

In the sample app, when the PhotoPage is loaded, the OnNavigatedTo method is called, which in turn calls the LoadPhoto method.

private async void LoadPhoto()
{
    var file = await _repository.GetPhotoAsync(_filePath);
    var imageData = await file.OpenReadAsync();
    var decoder = await BitmapDecoder.CreateAsync(imageData);
 
    _width = Convert.ToInt32(decoder.PixelWidth);
    _height = Convert.ToInt32(decoder.PixelHeight);
    _bmp = new WriteableBitmap(_width, _height);
 
    imageData.Seek(0);
    await _bmp.SetSourceAsync(imageData);
    Photo = _bmp;
    OnPropertyChanged("Photo");
}

This method simply loads the photo from disk, and decodes it for display in a WriteableBitmap. The pixel data in a WriteableBitmap is stored in the PixelBuffer property. However, this property is read-only. In managed languages, you can use the AsStream extension method (from the System.Runtime.InteropServices.WindowsRuntime namespace) to access the underlying buffer as a stream. To see how to access the underlying buffer in C++/CX, see this blog post.

// Get source pixel data
var srcPixelStream = _bmp.PixelBuffer.AsStream();
byte[] srcPixels = new byte[4 * _width * _height];
int length = srcPixelStream.Read(srcPixels, 0, 4 * _width * _height);
 
// Convert to greyscale
byte[] destPixels = Imaging.ToGreyscale(srcPixels, _width, _height);

The code above accesses the underlying buffer in the WriteableBitmap as a stream, creates a new byte array to store the pixel data, and then reads the pixel data from the stream to the byte array. Then the ToGreyscale method is called to convert the pixel data to greyscale.

public static byte[] ToGreyscale(byte[] srcPixels, int width, int height)
{
    byte b, g, r, a, luminance;
    byte[] destPixels = new byte[4 * width * height];
 
    // Convert pixel data to greyscale
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            b = srcPixels[(x + y * width) * 4];
            g = srcPixels[(x + y * width) * 4 + 1];
            r = srcPixels[(x + y * width) * 4 + 2];
            a = srcPixels[(x + y * width) * 4 + 3];
            luminance = Convert.ToByte(0.299 * r + 0.587 * g + 0.114 * b);
 
            destPixels[(x + y * width) * 4] = luminance;     // B
            destPixels[(x + y * width) * 4 + 1] = luminance; // G
            destPixels[(x + y * width) * 4 + 2] = luminance; // R
            destPixels[(x + y * width) * 4 + 3] = luminance; // A
 
        }
    }
 
    return destPixels;
}

The ToGreyscale method iterates through the srcPixel byte array, converting each value to its equivalent greyscale representation, before returning it to the calling method. Note that the pixel data is stored in BGRA format.

// Write greyscale image back to WriteableBitmap
srcPixelStream.Seek(0, SeekOrigin.Begin);
srcPixelStream.Write(destPixels, 0, length);
_bmp.Invalidate();

Back in the calling method the stream that accessed the underlying buffer in the WriteableBitmap has its position reset to the beginning. Then the destPixels byte array, containing the greyscale representation of the image data, is written back to the stream, and hence to the underlying WriteableBitmap. A call is made to the WriteableBitmap.Invalidate method to request a redraw of the entire bitmap.

Summary

The pixel data in a WriteableBitmap is stored in the PixelBuffer property. However, this property is read-only. In managed languages, you can use the AsStream extension method (from the System.Runtime.InteropServices.WindowsRuntime namespace) to access the underlying buffer as a stream. You can then use the Read and Write methods on the stream to access the pixel data and replace it.

The sample app can be downloaded here.

Monday, 10 June 2013

Changing the Default Conventions used in Prism for the Windows Runtime

Prism for the Windows Runtime specifies a ViewModelLocator object, that can be used to manage the instantiation of view models and their associations to views. This approach has the advantage that there’s a single class that’s responsible for view model instantiation.

The ViewModelLocator class uses an attached property, AutoWireViewModel, to associate view models with views. In the view’s XAML this attached property is set to true to indicate that the view model should be automatically connected to the view. When the property is set to true the AutoWireViewModelChanged event handler (in the ViewModelLocator object) runs which first attempts to resolve the view model from any mappings that have been registered by the Register method of the ViewModelLocator object (for more info see my previous blog post). If the view model cannot be resolved using this approach, the method falls back to using a convention-based approach to resolve the correct view model type. This convention assumes that:

  1. View models are in the same assembly as the view types.
  2. Views are in a .Views child namespace.
  3. View names end with “Page”.
  4. View models are in a .ViewModels child namespace.
  5. View model names correspond with view names and end with “ViewModel”.

Using this convention, a view named MainPage must be located in a .Views child namespace, with its view model being named MainPageViewModel, which resides in a .ViewModels child namespace in the same assembly.

However, Prism doesn’t force you to use this convention. If you wish to change it, you can. For instance, you may choose to have your view models in a separate assembly.

Overriding Prism’s Default Conventions

In order to demonstrate how to override Prism’s default conventions I’ve modified my sample PhotoViewer app so that both views and view models reside in the same Pages folder and .Pages child namespace.

pages

Prism’s default convention specifies that Views can be located in a .Views child namespace. In order to override this convention the FrameNavigationService object must be configured to look for views in a location other than the Views folder. This can be achieved by overriding the GetPageType method (from the MvvmAppBase class) in the App class, and by adding code to define the page location and naming convention.

protected override Type GetPageType(string pageToken)
{
    var assemblyQualifiedAppType = this.GetType().GetTypeInfo().AssemblyQualifiedName;
    var pageNameWithParameter = assemblyQualifiedAppType.Replace(this.GetType().FullName, this.GetType().Namespace + ".Pages.{0}Page");
    var viewFullName = string.Format(CultureInfo.InvariantCulture, pageNameWithParameter, pageToken);
    var viewType = Type.GetType(viewFullName);
    return viewType;
}

This method simply redefines the convention for locating and naming views by specifying that they can be located in a .Pages child namespace, and that view names end with “Page”. If the app is run at this point the MainPage will be displayed, but it will be devoid of photo thumbnails because the MainPageViewModel will not be supplying any data to the view as it can’t be located.

To solve this problem the ViewModelLocator class must be configured to look for view models in a location other than the ViewModels folder in the same assembly. This can be achieved by overriding the OnInitialize method (from the MvvmAppBase class) in the App class, and invoking the static ViewModelLocator.SetDefaultViewTypeToViewModelTypeResolver method, passing in a delegate that specifies a view type and returns a corresponding view model type.

protected override void OnInitialize(IActivatedEventArgs args)
{
    _container.RegisterInstance<INavigationService>(NavigationService);
    _container.RegisterType<IRepository, FileSystemRepository>(new ContainerControlledLifetimeManager());
 
    ViewModelLocator.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
        {
            var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "PhotoViewer.Pages.{0}ViewModel, PhotoViewer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=495efabf0725380b", viewType.Name);
            var viewModelType = Type.GetType(viewModelTypeName);
            return viewModelType;
        });
}

As previously explained, the method first registers the NavigationService instance and FileSystemRepository type with the Unity container, so that the view model classes can take dependencies on them. The delegate passed into the SetDefaultViewTypeToViewModelTypeResolver method then simply redefines the convention for locating view models by specifying that they can be located in the PhotoViewer.Pages namespace, and that view model names end with “ViewModel”.

While the convention I’ve adopted here is not recommended, it does demonstrate how to override the default convention specified by Prism. For small apps the default convention will most likely suffice. However, for larger apps you may wish to move your view models into a separate assembly, such as a PCL.

Summary

You do not have to use the default conventions that are defined by Prism to locate and name views and views models. To change the convention for naming and locating views you can override the GetPageType method in your App class. To change the convention for naming, locating, and associating view models with views you should invoke the static ViewModelLocator.SetDefaultViewTypeToViewModelTypeResolver method, and pass in a delegate that specifies a view type and returns a corresponding view model type.

The sample app can be downloaded here.

Thursday, 6 June 2013

Building a Windows Store app using Prism and manual dependency injection

Previously I’ve demonstrated how to use Prism for the Windows Runtime by writing a sample photo viewing app. In the app there are two pages. The first page presents a thumbnail gallery view of photos in the users Pictures library. Clicking on a thumbnail takes the user to the second page which displays the full image. In the app, support for MVVM, navigation, and state management are all provided by Prism for the Windows Runtime.

The app registered types and instances that are used in the view model constructors with the Unity dependency injection container. However, you are not required to use Unity, or any other dependency injection container, when bootstrapping Windows Store apps using Prism. An alternative approach is to perform manual dependency injection to pass client service references to view models by registering factory methods against view types, in the App.OnInitialize method.

protected override void OnInitialize(IActivatedEventArgs args)
{
    var FileSystemRepository = new FileSystemRepository();
    ViewModelLocator.Register(typeof(MainPage).ToString(), () => new MainPageViewModel(FileSystemRepository, NavigationService));
    ViewModelLocator.Register(typeof(PhotoPage).ToString(), () => new PhotoPageViewModel(FileSystemRepository, NavigationService));
}

This method creates a singleton from the FileSystemRepository class, The FileSystemRepository class provides image data for display on both pages of the app. The OnInitialize method then registers a factory method for each view type with the static ViewModelLocator object, This ensures that the ViewModelLocator object instantiates the correct view model object for a view type, passing in dependent services to the view model constructor from the factory method. This alternative approach avoids using a dependency injection container, for those who prefer not to.

Summary

Prism for the Windows Runtime can accelerate the development of Windows Store apps by providing support for MVVM, loosely coupled communication, and the core services required in Windows Store apps. As well as allowing you to use a container for dependency resolution and construction, Prism also allows you to explicitly specify how to construct a view model for a given view type.

The sample app can be downloaded here.

Master Navigation in Windows Store Apps

Brian Noyes recently delivered a session at TechEd North America on mastering navigation in Windows Store apps. The video of the session is now online, and is well worth a watch if you want a dive into how to perform navigation using Prism for the Windows Runtime.

Building Windows Store Line-of-Business Applications

Brian Noyes recently delivered a session at TechEd North America on building Windows Store LOB apps. The video of the session is now online, and is well worth a watch if you want an overview of Prism for the Windows Runtime.