Monday, 29 October 2012

Announcing Hilo

Hilo is a Windows Store app I helped patterns & practices to develop earlier in the year. The app, developed using C++ and XAML, is an end-to-end app that demonstrates modern development practices for building Windows Store apps. The app, along with the accompanying guidance documentation, demonstrates to Windows Store app developers how to:

  • Implement common functionality for apps, such as tiles, pages, controls, navigation, file system integration, and suspend/resume.
  • Implement the Model-View-ViewModel (MVVM) and Repository patterns.
  • Use modern C++ effectively in apps.
  • Implement asynchronous programming to make an app fast and fluid.
  • Use Accelerated Massive Parallelism (AMP) to offload intensive computation to the GPU.
  • Make an app ready for the global market.
  • Test and app and tune its performance.

The app has now been released as a Windows 8 SDK sample, and can be downloaded here. The documentation can be found on the Windows Dev Center here.

Monday, 22 October 2012

Suspend/resume/activation in a C++/CX app

Previously I extended the sample photo viewing app so that the user can covert a colour photo to greyscale, on the PhotoView page. This used MVVM and commands to bind the Command property of a Checkbox control to an ICommand property on the PhotoViewModel. When the control’s command is invoked, the code in the view model is executed. The advantage of this approach is that it allows you to reduce (and in some cases completely eliminate) the amount of code in the code-behind file for the view, while also promoting the testability of the app.

I’ve also written about an approach to page navigation in C++/CX apps, which allows the page navigation history to be serialized during suspension and de-serialized when the app is resumed.

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 IsChecked property of the PhotoViewModel class will be serialized/de-serialized so that when the app reactivates following suspension, the state of the Checkbox control will be identical to when the app was suspended.

For information on the application lifecycle see Application lifecycle, Guidelines for app suspend and resume, and the Hilo project.

Implementation

Suspend

When you create a new Windows Store app in C++/CX the App class registers an event handler for the Suspending event, which is used to serialize app and user data. This event handler invokes the SaveAsync method in the SuspensionManager class, which is a helper class created by Visual Studio, to write the current session state to disk. The SaveAsync method invokes the SaveFrameNavigationState method in the SuspensionManager class, which invokes the GetNavigationState method on the Frame object, in order to serialize the Frame navigation history into a string. In turn, the GetNavigationState method invokes the OnNavigatedFrom method of the frame’s associated page object.

In the sample app, each page is an instance of the PhotoViewerPage class. The OnNavigatedFrom method of the PhotoViewerPage class invokes the OnNavigatedFrom method of the view model associated with the current page, and then invokes the OnNavigatedFrom method of its base class, LayoutAwarePage.

void LayoutAwarePage::OnNavigatedFrom(NavigationEventArgs^ e)
{
    auto frameState = SuspensionManager::SessionStateForFrame(Frame);
    auto pageState = ref new Map<String^, Object^>();
    SaveState(pageState);
    frameState->Insert(_pageKey, pageState);
}

The OnNavigatedFrom method of the LayoutAwarePage class gets the frame state from the suspension manager, and then calls the page’s SaveState method to update the frame state with data for the current page.

void PhotoViewerPage::SaveState(IMap<String^, Object^>^ pageState)
{
    auto vm = dynamic_cast<ViewModelBase^>(DataContext);
    if (vm != nullptr)
    {
        auto vmStateMap = ref new Map<String^, Object^>();
        vm->SaveState(vmStateMap);
 
        pageState->Insert(viewModelStateKey, vmStateMap);
    }
}

In the sample app, page state is saved through the associated view model, using a single key/value pair for the page’s data.

void PhotoViewModel::SaveState(IMap<String^, Object^>^ stateMap)
{
    if (m_file != nullptr)
    {
        stateMap->Insert(IsGreyscaleMapKey, m_isGreyscale);
    }
}

The SaveState method of the PhotoViewModel class saves the value of the m_isGreyscale member variable, which represents whether the photo on the PhotoView page should be displayed in greyscale or not.

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 etc. For more information see the Hilo project.

Activation

Windows may terminate an app after it has been suspended, if the system is low on resources. When an app is activated, the OnLaunched method of the App class will be invoked. The OnLaunched method will examine whether the app was terminated following suspension, and if it was, will invoke the RestoreAsync method of the SuspensionManager class in order to deserialize any frame and page state. The RestoreAsync method reads the saved state data and then calls the SetNavigationState method for each frame that was previously saved. In turn, the SetNavigationState method invokes the OnNavigatedTo method of the frame’s associated page object.

As previously mentioned, in this app each page is an instance of the PhotoViewerPage class. The OnNavigatedTo method of the PhotoViewerPage class invokes the OnNavigatedTo method of the view model associated with the current page, and then invokes the OnNavigatedTo method of its base class, LayoutAwarePage.

The OnNavigatedTo method of the PhotoViewModel class simply extracts the saved navigation data from the parameter and updates the view model.

void PhotoViewModel::OnNavigatedTo(NavigationEventArgs^ e)
{
    auto navigationData = dynamic_cast<String^>(e->Parameter);
    PhotoNavigationData photoData(navigationData);
    Initialize(photoData.GetFilePath());
}

The OnNavigatedTo method of the LayoutAwarePage gets the previously saved state for the page from the SuspensionManager class and invokes the page’s LoadState method to deserialize the page’s saved state and restore it.

void PhotoViewerPage::LoadState(Object^ navigationParameter, IMap<String^, Object^>^ pageState)
{
    auto vm = dynamic_cast<ViewModelBase^>(DataContext);
    if (vm != nullptr && pageState != nullptr)
    {
        IMap<String^, Object^>^ state = nullptr;
        state = dynamic_cast<IMap<String^, Object^>^>(pageState->Lookup(viewModelStateKey));
 
        vm->LoadState(state);
    }
}

In the sample app, page state is restored through the associated view model, using a single key/value pair for the page’s data.

void PhotoViewModel::LoadState(IMap<String^, Object^>^ stateMap)
{
    if (stateMap != nullptr)
    {
        m_isGreyscale = static_cast<bool>(stateMap->Lookup(IsGreyscaleMapKey));
    }
}

The LoadState method of the PhotoViewModel class restores the previously saved value of the m_isGreyscale member variable, which represents whether the photo on the PhotoView page should be displayed in greyscale or not. The overall effect 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 extend the app so that along with frame state, page state can be serialized during suspension and de-serialized when the app reactivates. Specifically, the IsChecked property of the PhotoViewModel class was serialized/de-serialized so that when the app reactivates following suspension, the state of the Checkbox control is identical to when the app was suspended.

The sample application can be downloaded here.

Monday, 15 October 2012

MVVM and commands in a C++/CX app

Previously I demonstrated how to implement the MVVM pattern in C++/CX, through a small sample app that allows the user to view the photos in their Pictures library. Since then I’ve enhanced the app by using the Repository pattern, adding design-time data, and by passing serializable objects when navigating between pages. I also wrote about how to access pixel data in a C++/CX Windows Store app.

In the MVVM blog post I mentioned that you can use data binding for UI controls that cause the app to perform operations, by binding the control’s Command property to an ICommand property on a view model. This applies to any controls that derive from ButtonBase. When the control’s command is invoked, the code in the view model is executed. The advantage of this approach is that it allows you to reduce (and in some cases, completely eliminate) the amount of code in the code-behind file for the view, and it helps to promote the testability of your app.

In this blog post I’ll further extend the app so that the user can convert a photo to greyscale, on the PhotoView page. In order to do this I’ll bind the Command property of a Checkbox control to an ICommand property on the PhotoViewModel.

Implementation

I’ve added a Checkbox control to the PhotoView page, to control whether the photo should be displayed in colour or greyscale. The Checkbox binds the IsChecked property to the IsGreyscale property on the PhotoViewModel class, to determine whether the Checkbox is checked or not. For details of how the view binds to properties on the view model see MVVM in C++/CX, and the Hilo project.

<CheckBox Command="{Binding GreyscaleCommand}" 
          IsChecked="{Binding Path=IsGreyscale, Mode=TwoWay}" />
The Checkbox also binds the Command property to the GreyscaleCommand property on the PhotoViewModel class, which is of type ICommand. The GreyscaleCommand property simply returns a member variable that contains a reference to a command implementation that describes the command logic.
ICommand^ PhotoViewModel::GreyscaleCommand::get()
{
    return m_greyscaleCommand;
}
The m_greyscaleCommand member variable is initialized in the PhotoViewModel constructor. This initialization sets the method that will be invoked when the user toggles the state of the Checkbox.
m_greyscaleCommand = ref new DelegateCommand(ref new ExecuteDelegate(this, &PhotoViewModel::ConvertPhotoToGreyscale), nullptr);
The m_greyscaleCommand is set to an instance of the DelegateCommand class, which was developed for the Hilo project. The DelegateCommand specifies an ExecuteDelegate and a CanExecuteDelegate. The ExecuteDelegate is used to specify a method to be invoked when the command is executed, with the CanExecuteDelegate specifying a method to be invoked to determine whether or not the command can be executed. However, in this scenario as we always want the command to be able to execute, a nullptr is passed to the CanExecuteDelegate.

The ExecuteDelegate specifies that the ConvertPhotoToGreyscale method will be invoked when the command is executed by the user toggling the state of the Checkbox. This method uses the WriteableBitmap type to manipulate the pixel values in order to convert them to their greyscale representation. For more information see Accessing Image Pixel Data in a C++/CX Windows Store App.

void PhotoViewModel::ConvertPhotoToGreyscale(Object^ parameter)
{
    if (!m_isGreyscale)
    {
        m_photo = nullptr;
        OnPropertyChanged("Photo");
        return;
    }
 
    unsigned int width = m_photo->PixelWidth;
    unsigned int height = m_photo->PixelHeight;
 
    // Create destination bitmap
    WriteableBitmap^ destImage = ref new WriteableBitmap(width, height);
 
    // Get pointers to the source and destination pixel data
    byte* pSrcPixels = GetPointerToPixelData(m_photo->PixelBuffer);
    byte* pDestPixels = GetPointerToPixelData(destImage->PixelBuffer);
 
    // Convert pixel data to greyscale
    parallel_for(0u, height, [width, pSrcPixels, pDestPixels](unsigned int y)
    {
        for (unsigned int x = 0; x < width; x++)
        {
            byte b = pSrcPixels[(x + y * width) * 4];
            byte g = pSrcPixels[(x + y * width) * 4 + 1];
            byte r = pSrcPixels[(x + y * width) * 4 + 2];
            byte a = pSrcPixels[(x + y * width) * 4 + 3];
            byte luminance = static_cast<byte>(0.299 * r + 0.587 * g + 0.114 * b);
 
            pDestPixels[(x + y * width) * 4] = luminance;      // B
            pDestPixels[(x + y * width) * 4 + 1] = luminance; // G
            pDestPixels[(x + y * width) * 4 + 2] = luminance; // R
            pDestPixels[(x + y * width) * 4 + 3] = a;         // A
        }
    });
 
    // Update image on screen
    m_photo = destImage;
    OnPropertyChanged("Photo");
}
The ConvertPhotoToGreyscale method uses the PPL’s parallel_for function to perform an operation using the computer's multicore hardware. The code parallelizes the outer loop only because it performs enough work to benefit from the overhead for parallel processing. If you parallelize the inner loop, you will not receive a gain in performance because the small amount of work that the inner loop performs does not overcome the overhead for parallel processing.

The method also includes functionality to reset the photo from greyscale to colour by forcing the original photo to be reloaded from the file system. Note that this approach is merely illustrative in order to include the functionality, and does not offer the user experience recommended for a Windows Store app.

Summary


Data binding can be used for UI controls that cause an app to perform operations, by binding the control’s Command property to an ICommand property on a view model. This applies to any controls that derive from ButtonBase. When the control’s command is invoked, the code in the view model is executed. The advantage of this approach is that it allows you to reduce (and in some cases, completely eliminate) the amount of code in the code-behind file for the view, and it helps to promote the testability of your app.

The sample application can be downloaded here.

Wednesday, 10 October 2012

Navigating between pages in a C++/CX app

Previously I’ve developed a small photo viewing sample app to show how to implement a Windows Store app that supports design-time data, and uses the MVVM and Repository patterns to separate concerns. The app also includes code to navigate between pages, allowing navigation to be requested from both views and view models.

For example, when a photo thumbnail is clicked on the first page of the app, the second page of the app is navigated to and the clicked upon photo is shown. This functionality is invoked by the event handler shown below.

void MainView::OnPhotoClick(Object^ sender, ItemClickEventArgs^ e)
{
    auto photo = dynamic_cast<Windows::Storage::BulkAccess::FileInformation^>(e->ClickedItem);
    if (photo != nullptr)
    {
        PhotoViewerPage::NavigateToPage(PageType::Photo, photo);
    }
}

The event handler invokes the NavigateToPage method of the PhotoViewerPage class, passing the page to be navigated to and a parameter to pass to the page, in this case a FileInformation object representing the photo to be loaded on the Photo page. While this gives the desired result it creates a problem if the app is suspended after navigation has occurred.

When you create a new Windows Store app project in C++/CX the App class registers an event handler for the Suspending event. This event handler invokes the SaveAsync method in the SuspensionManager class, which is a helper class created by Visual Studio. In turn, the SaveAsync method invokes the SaveFrameNavigationState method in the SuspensionManager class, which invokes the GetNavigationState method on the Frame object, in order to serialize the Frame navigation history into a string. However, the GetNavigationState method doesn’t support serialization of any complex object parameter types which were passed to Frame->Navigate (which is invoked by PhotoViewerPage::NavigateToPage). Instead, it only supports serialization of primitive types. Therefore, in order to to allow the Frame navigation history to be serialized when the app is suspending, the parameter passed during page navigation must be a primitive type, rather than a FileInformation object.


Implementation


In order to to allow the Frame navigation history to be serialized when the app is suspending, the parameter passed during page navigation must be a primitive type, rather than a FileInformation object. This is the role of the PhotoNavigationData class. This class is a pure C++ class, rather than a ref class. This is because ref classes should only be used for interop with the Windows Runtime. For more information see the Hilo project.

PhotoNavigationData::PhotoNavigationData(FileInformation^ file)
{
    m_filePath = file->Path;
}
 
PhotoNavigationData::PhotoNavigationData(String^ serializedData)
{
    wstring data(serializedData->Data());
    m_filePath = ref new String(data.c_str());
}
 
String^ PhotoNavigationData::GetFilePath() const
{
    return m_filePath;
}
 
String^ PhotoNavigationData::SerializeToString()
{
    wstringstream stringStream;
    stringStream << m_filePath->Data();
    return ref new String(stringStream.str().c_str());
}

This class has two constructors. The first constructor takes a FileInformation object and stores the Path property of the object in a member variable. The second constructor takes a serialized String and stores it in a member variable. The GetFilePath method simply returns the member variable, and the SerializeToString method takes the member variable and turns it into a serialized String.

Note: in this example the PhotoNavigationData class can be thought of as overkill, as it ultimately takes a piece of data of type String (the Path property of the FileInformation object), and returns the data as a new String. However, this class has been developed for extensibility, for scenarios where you may need to pass a piece of data that is not a String, or where you may need to pass more than one piece of data, such as a String and a Date. This would be useful, for example, for pages that execute a query against the file system based upon a date range.

Then on the first page of the application when the user clicks on a thumbnail, in order to invoke page navigation, the event handler code becomes as shown below.

void MainView::OnPhotoClick(Object^ sender, ItemClickEventArgs^ e)
{
    auto photo = dynamic_cast<Windows::Storage::BulkAccess::FileInformation^>(e->ClickedItem);
    if (photo != nullptr)
    {
        PhotoNavigationData photoData(photo);
        PhotoViewerPage::NavigateToPage(PageType::Photo, photoData.SerializeToString());
    }
}

Here, once the FileInformation object for the clicked upon thumbnail is retrieved, a new PhotoNavigationData object is created using stack semantics. When PhotoViewerPage::NavigateToPage is invoked, the first parameter remains the page to be navigated to, but the second parameter becomes a call to SerializeToString on the instance of the PhotoNavigationData object.

When the Photo page is loaded, the OnNavigatedTo event handler in the PhotoViewModel class is executed. This deserializes the String passed to the page, and invokes the GetFilePath method on the PhotoNavigationData instance in order to pass the path of the FileInformation object to the Initialize method, where it’s stored as a member variable.

void PhotoViewModel::OnNavigatedTo(NavigationEventArgs^ e)
{
    auto navigationData = dynamic_cast<String^>(e->Parameter);
    PhotoNavigationData photoData(navigationData);
    Initialize(photoData.GetFilePath());
}
 
void PhotoViewModel::Initialize(String^ path)
{
    m_photo = nullptr;
    m_path = path;
}

The benefit of this approach is that it enables the suspend/resume process for this sample app, as the Frame navigation history, which is serialized to disk when the app is suspended/terminated and deserialized when the app re-activates, contains the path of the FileInformation object to load on the Photo page. This means that if the app is suspended/terminated when the Photo page is active, upon re-activation the photo the user had selected before suspension will be re-loaded.

As I’ve previously stated, this may be seen as overkill for this simple example app, but it shows an approach that can be used when the parameter to be passed is not a String, or when more than one parameter needs to be passed to a page.


Summary


When an app is suspended, the Frame navigation history is serialized into a string by the GetNavigationState method. However, the GetNavigationState method doesn’t support serialization of any complex object parameter types which were passed to Frame->Navigate. Instead, it only supports serialization of primitive types. The PhotoNavigationData class shows an approach that enables data to be passed to a page as a primitive type, thus allowing the Frame navigation history to be serialized during suspension.

The sample application can be downloaded here.