Channels ▼
RSS

Design

Customizing the Appearance of Windows 8 Apps


It is useful to take a look at the different default styles for the different elements and the animations. In this way, you can see the expected behavior for each of the elements whenever the app shows them.

If you want to override specific styles, it is convenient to create a new ResourceDictionary and merge the existing StandardStyles.xaml within the new one. For example, the following lines do that in a new ResourceDictionary defined in DrDobbsStyles.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wui="using:Windows.UI.Xaml"
    xmlns:local="using:DrDobbsApp.Common">

    <wui:ResourceDictionary.MergedDictionaries>
        <wui:ResourceDictionary Source="StandardStyles.xaml"/>
    </wui:ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Then, you need to define each new or overridden style in the new DrDobbsStyles.xaml and you need to replace the default dictionary with DrDobbsStyles.xaml in App.xaml:

<ResourceDictionary Source="Common/DrDobbsStyles.xaml"/>

Understanding the Default Application Behavior for a Grid App

The following lines show the code for App.xaml.cs. The App constructor specifies an event handler (OnSuspending) that is fired when the app transitions to the Suspended state.

sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    protected override async void OnLaunched(LaunchActivatedEventArgs args)
    {
        Frame rootFrame = Window.Current.Content as Frame;

        // Do not repeat app initialization when the Window already has content,
        // just ensure that the window is active
        if (rootFrame == null)
        {
            // Create a Frame to act as the navigation context and navigate to the first page
            rootFrame = new Frame();
            //Associate the frame with a SuspensionManager key                                
            SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

            if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
            {
                // Restore the saved session state only when appropriate
                try
                {
                    await SuspensionManager.RestoreAsync();
                }
                catch (SuspensionManagerException)
                {
                    //Something went wrong restoring state.
                    //Assume there is no state and continue
                }
            }

            // Place the frame in the current Window
            Window.Current.Content = rootFrame;
        }
        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            if (!rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups"))
            {
                throw new Exception("Failed to create initial page");
            }
        }
        // Ensure the current window is active
        Window.Current.Activate();
    }

    private async void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        await SuspensionManager.SaveAsync();
        deferral.Complete();
    }
}

Notice that OnSuspending uses the async keyword and calls the asynchronous SuspensionManager.SaveAsync method with the await keyword. This way, the app preserves its navigation state. Each view in the Grid app inherits from LayoutAwarePage and overrides the LoadState method to recreate the view from a prior session. The Grid app includes a SuspensionManager class in the Common folder and simplifies the process-lifetime management for the app.

The App class overrides the OnLaunched event that also uses the async keyword and calls the asynchronous SuspensionManager.RestoreAsync method with the await keyword only when it is necessary to restore a saved session state, based on the previous execution state (args.PreviousExecutionState).

Windows.ApplicationModel.Activation.ApplicationExecutionState is the enum with all the possible app execution states. Figure 9 shows the different state transitions and the event handlers fired during each state transition in the App class. For example, when the application transitions from the Running state to Suspended, the App class fires the Suspending event handler. In the Grid app template, Suspending invokes the OnSuspending event handler method. The app can also transition to Terminated or ClosedByUser states. When Windows determines there are resource constraints, it can decide to terminate an app and you can restore session data when Terminated is the previous execution state. Thus, the previous execution states provide valuable information for the app to determine what it should do.


Figure 9: State transitions for a Windows 8 app and the event handlers that the app fires in the App class.

There are many reasons why an app might be activated and activation depends on many contracts and extensions. Of course, if the user taps or clicks on the app's tile, the app will launch and become activated. However, if your app provides search services, the app might be activated when the user wants to search with your app.

When users tap or click the app's tile, the app will invoke the OnLaunched even handler method. The previously shown code for the OnLaunched event creates a new frame (Windows.UI.Xaml.Controls.Frame) instance and registers it with the SuspensionManager. The frame acts as the navigation context. Then, the code places the frame in the current window, navigates to the first page when the navigation status isn't restored, and makes sure the current window is active by calling Window.Current.Activate. The following lines navigate to the first page, GroupedItemsPage, and pass "AllGroups" as the parameter indicating that it is necessary to display all the groups:

if (!rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups"))
{
    throw new Exception("Failed to create initial page");
}

The call to the Navigate method will launch the OnNavigatedTo event handler for LayoutAwarePage. Remember that GroupedItemsPage inherits from LayoutAwarePage (found in the Common folder). OnNavigatedTo calls the LayoutAwarePage.LoadState method, overridden in GroupedItemsPage with the following lines:

protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter);
    this.DefaultViewModel["Groups"] = sampleDataGroups;
}
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter);
    this.DefaultViewModel["Groups"] = sampleDataGroups;
}

Thus, GroupedItemsPage.LoadState is retrieving the groups from the sample data source defined in the SampleDataSource class. The SampleDataSource.GetGroups method returns an IEnumerable<SampleDataGroup>, but the original variable is an ObservableCollection<SampleDataGroup>.

Each group is an instance of SampleDataGroup that has an ObservableCollection<SampleDataItem> with all the items. SampleDataGroup also has a subset of that SampleDataItem collection to allow virtualizing large items collections. Thus, the Grid app displays a maximum of 12 items at a time. Obviously, it is necessary to replace the sample data source provided by default in the Grid app template with a call to a Web service in order to retrieve external data.

Conclusion

In this article, I explained how to edit the app manifest, change the various required images, and override brushes and styles used in the Grid app template. In the next article, I'll create a new REST service from scratch, based on the new ASP.NET Web API introduced in .NET Framework 4.5. After creating the REST service, I'll show how to consume it in the sample Grid app by using the new asynchronous methods provided by the System.Net.HttpClient.

Related Reading

Writing Your First Windows 8 App: The Lay of the Land

Access Data with REST in Windows 8 Apps


Gaston Hillar is a frequent contributor to Dr. Dobb's on the topic of Microsoft development.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video