Random geekery since 2005.

Husband, father, programmer, speaker, writer, blogger, podcaster, collector, traveler, golfer.

31 Days of Windows 8 | Day #5: Settings Contract

Written in

by

This article is Day #5 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

31 Days of Windows 8

day5-charms-sideToday we are kicking off a series of posts focused on contracts, starting with Application Settings. The chances are pretty high that your app has them, and you know you hate dealing with them. Application settings are just one part of something bigger in Windows 8 called contracts.  Let’s start our conversation on Settings with a Microsoft definition of contracts:

Contracts A contract is like an agreement between one or more apps. Contracts define the requirements that apps must meet to participate in these unique Windows interactions.

For example, Windows lets users share content from one app to another. The app that shares content out supports a source contract by meeting specific requirements, while the app that receives the shared content supports a target contract by meeting a different set of requirements. Neither app needs to know anything about the other. Every app that participates in the sharing contract can be confident that the sharing workflow is completely supported, end-to-end, by Windows.

Interesting, this sounds like a “managed interface” between an application and the Windows Operating System. There are 5 contracts available to our applications:

  • File Picker
  • Play To
  • Search
  • Settings
  • Share

Just like a typical programming interface, this means hesheit who extends it is bolting on some type of functionality without the other actually knowing about it.

With Windows 8, this all actually feels like it happens at the user experience level. What do I mean? Well, let’s take the share contract as an example.  Simply put, applications tell the operating system what they would like to sign up for. In the case of sharing, maybe it’s accepting an image or sharing an image. Windows then will broker the rest.

Imagine a scenario where you find a great article while browsing the web in something like Internet Explorer. You want to share it to someone either in email or Twitter. Assuming you had an application installed that does email or Twitter, and they accepted sharing of an a URI, then Internet Explorer could share to those. Better yet, those applications don’t even have to be running to do so. Windows takes care of making all that awesomesauce happen.

Sounds like a typical programming interface, doesn’t it?

Starting Simple

If you look around at many of the examples out there, you’re going to find a complex set of methods spanning multiple pages, and if you’re anything like me, it’s going to be confusing.  This series of articles is meant to make topics like these simple to understand and use, so I’m going to do just that.

When our application starts up, there is a method in our App.xaml.cs file named OnLaunched that gets fired.  At the very beginning of OnLaunched, we are going to create an event handler for when the user attempts to open the SettingsPane.  Your elements are not added until the user tries to open the Settings Charm.  This event would also be used when you need to “pause” your app or game when the settings are opened.

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    SettingsPane.GetForCurrentView().CommandsRequested += App_CommandsRequested;
            
    Frame rootFrame = Window.Current.Content as Frame;
 
    ...

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

Once you’ve added the event handler, we can get down to adding SettingsCommands to our SettingsPane.  There are several steps to create a SettingsCommand:

  • Create a new SettingsCommand.  These require three properties: an ID, a label, and an action to perform when the command is pressed.  In our case, this will be creating a Popup control, populating it with a custom UserControl we will create, and sliding it in from the side of the screen.
  • Handle all of the cases for Popup dismissal.  We will also need to make sure that we clean up our mess, so we will need to manage how to get back to our application when the user has indicated they are done.

If you haven’t already generated it, you now need a method for your event handler named App_CommandsRequested, or whatever you chose to name it.  This is where we will do the bulk of our logic for getting the SettingsPane to behave the way we want.  Here’s what mine looks like:

void App_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
    SettingsCommand command = new SettingsCommand("about", "About This App", (handler) =>
    {
        Popup popup = BuildSettingsItem(new AboutPage(), 646);
        popup.IsOpen = true;
    });
 
    args.Request.ApplicationCommands.Add(command);
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see above, we create a new SettingsCommand object, and provide it with three values.  Unless you plan on changing your SettingsPane at runtime, the first one won’t matter to you much.  It’s a simple ID that you can use to reference the SettingsCommand later.  The label, “About This App,” can be any string value, but I would recommend keeping it under 40 characters, because more than that will be truncated.  Finally, we have our handler for this command.  This is the code that will be executed when the user taps on the label.  I’ve simplified this process by using a lambda expression to define the code inline, and you can see that I am creating a Popup control and setting its IsOpen property to true.  Changing this property is what makes the Popup appear on the screen.

Creating the Popup Control

In this section, we are going to take a look at the BuildSettingsItem method that I have created.  You may have noticed in that code sample above that we are passing two values.  The first is a custom UserControl that we will be creating shortly.  For now, just understand that AboutPage.xaml is a UserControl that we will have to create, and that it is used to populate our Popup control.

private Popup BuildSettingsItem(UserControl u, int w)
{
    Popup p = new Popup();
    p.IsLightDismissEnabled = true;
    p.ChildTransitions = new TransitionCollection();
    p.ChildTransitions.Add(new PaneThemeTransition()
    {
        Edge = (SettingsPane.Edge == SettingsEdgeLocation.Right) ?
                EdgeTransitionLocation.Right :
                EdgeTransitionLocation.Left
    });
 
    u.Width = w;
    u.Height = Window.Current.Bounds.Height;
    p.Child = u;
 
    p.SetValue(Canvas.LeftProperty, SettingsPane.Edge == SettingsEdgeLocation.Right ? (Window.Current.Bounds.Width - w) : 0);
    p.SetValue(Canvas.TopProperty, 0);
 
    return p;
}

Much of the code in this method is “fluffy,” which is to say it’s for making the UI a little more pretty and fluid.  The specific lines that are important are the last six.  We define the height and width of our UserControl, u, and then assign it as a child of our Popup control, p.  (Width is recommended to be 346 or 646, height should be the full height of the user’s screen, according to the guidance from Microsoft.)   Finally, we set the left and top properties of the popup so that it appears in the appropriate location, and pass the entire Popup back to our SettingsCommand.

SIDE NOTE: Windows 8 can actually transform a bit based on the localization settings that have been applied to the machine.  In countries where the language is read from right to left, the Charms Bar is actually located on the left side of the screen instead of the right.  This is why, when assigning the LeftProperty of our Popup, we have to check to see which “edge” the SettingsPane lives on.  You should see similar logic for the Edge of the PaneThemeTransition earlier in the method.

You certainly don’t have to break all of this code up into chunks like I have, but I think it makes things simpler, especially when you want to create multiple SettingsCommand elements.

Creating the UserControl

I promised earlier that we’d come back to this, and here we are.  At this point, we’ve taken care of all the scaffolding that is required to make the Settings Contract work.  Now all we have to do is build a page to be shown.  Add a new UserControl item to your project.  I’ve named mine AboutPage.xaml to match the code we wrote earlier, but you can use any name you’d like obviously.

5-AddUserControl

The code for this file is entirely up to you.  While there are recommendations on how your Settings panels should look, there aren’t any specific rules about it.  What I am providing you in the following code sample is a template of sorts.  It will make your application look like this:

5-SettingsPanelShowing

Ultimately, however, you can use any XAML code that you’d like to make your Popup shine.

<Border BorderBrush="#00b2f0" BorderThickness="1,0,0,0">
    <Grid Background="White" VerticalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
            
        <!-- HEADER -->
        <Grid Background="#00b2f0" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
 
            <StackPanel Orientation="Horizontal" Grid.Column="0" Margin="40, 32, 17, 13">
                <Button x:Name="BackButton" Margin="0,3,0,0" Style="{StaticResource BackButtonStyle}" Click="BackButton_Click"/>
                <TextBlock Margin="10,10,0,0" FontFamily="Segoe UI" FontWeight="SemiLight" FontSize="24.6667" Text="About This App" Foreground="White"/>
            </StackPanel>
            <Image Source="Assets/SmallLogo.png" Width="29" Height="29" Margin="353,46,17,21" />
        </Grid>
 
        <!-- CONTENT AREA -->
        <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1">
            <Grid Margin="40,33,40,39" VerticalAlignment="Top" Grid.RowSpan="3">
                <StackPanel>
                        
                </StackPanel>
            </Grid>
        </ScrollViewer>
    </Grid>
</Border>

There’s nothing substantially complicated about this layout…we have three controls that are actually important for the header:

  • Button – The Button control is the circled arrow.  We’ve rigged up a click event for this named BackButton_Click, and I’ll show you that code in the final step of this article.
  • TextBlock – This contains the name of the Settings the user is actively looking at.  In most cases, this should match the words that you show in the SettingsPane.
  • Image – This image certainly isn’t required, but constant reinforcement of your branding and logo goes a long way.  I can’t recommend showing your logo as often as possible, and this is a great place to do so.

At the bottom, we have a section marked Content Area.  Inside the embedded StackPanel control is where you should add your content.  This can be anything, but try to keep it simple.  CheckBox, ToggleButton, TextBox, RadioButton, etc.  Simple controls with an eye on performing one simple task.

Here’s the code for the BackButton_Click method:

private void BackButton_Click(object sender, RoutedEventArgs e)
{
    Popup parent = this.Parent as Popup;
    if (parent != null)
    {
        parent.IsOpen = false;
    }
 
    // If the app is not snapped, then the back button shows the Settings pane again.
    if (Windows.UI.ViewManagement.ApplicationView.Value != Windows.UI.ViewManagement.ApplicationViewState.Snapped)
    {
        SettingsPane.Show();
    }
}

You can see that we close our parent Popup control, and if the app is not currently in a snapped state, re-open the SettingsPane, as a good back button should.  So that’s about it!

Oh.  Wait.  You wanted to know how to SAVE the user’s data?

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Saving Data

Windows 8 has changed many things, but one of the core user behaviors that has gone away is the concept of a “Save” button.  As much as possible, I want you to eliminate that concept from your mind.

When a user changes a value in their settings,

DO NOT wait for them to click a “Save” button.

DO NOT prompt them with an “Are you sure?” dialog box when the change is reversible.

Save the data the moment they change it, and give your user enough credit to make the changes they want to make.  If they click a “delete all your data” option, that might be a reason to confirm that they’re sure.  But only do it because it’s not reversible.  Not because you think your user is an idiot.

As for the HOW, we’re going to wait on that topic until Day #8, and then we will spend the entire time focused on saving data both locally on the device, as well as roaming those values across all of the machines the user has an account on.

Summary

When I was first introduced to Windows 8 I kept hearing the phrase, “Win as 1”. Win as 1 is one of the core tenets for  Windows. At first this just sounds like standard  marketing speak but actually it’s really far from that. Having now worked with Windows 8 for some time, the contracts are great proof point of this tenet. Things like application settings are now centralized for the user, our applications can now spend more time focusing on delivering their core features rather than dealing with things like settings. Furthermore, now that the settings are consistent across all applications, we only ever have to teach a user once to use settings across all applications.

“I only had to be taught how to open a door once and then I could open all doors.”

— I made that up.

Today, we took a look the Settings Contract, which is just one of many contracts you will find in Windows 8. Just like a programming interface, contracts in Windows 8 offer your app a unique way to extend your application beyond the traditional definition of an “application process” while providing a consistent user interface to our users.

You can download the entire sample solution here here:

 downloadXAML

Tomorrow, we’re going to look at the Search contract.  Search is something you’ll come to find great value in, not only from a usability perspective, but also because it’s a great way to continue to get your application in front of your users. See you then!

downloadTheTools

Tags

7 responses to “31 Days of Windows 8 | Day #5: Settings Contract”

  1. B. Clay Shannon Avatar

    Thanks; great article.

    Nitpick: “tenant” – I don’t think that word means what you think it means. A tenant is synonymous with a renter or inhabitant. Based on the context in which it was used, I think you want “tenet.”

    1. jeffblankenburg Avatar
      jeffblankenburg

      That’s what I get for not reading it more closely. Thanks!

  2. […] 31 Days of Windows 8 | Day #5: Settings Contract – Jeff Blankenburg […]

  3. […] Read original post by Jeff Blankenburg at BlankenBlog […]

  4. […] 31 días de Windows 8 | Día 5: El contrato de configuraciones by Amin Espinoza on Jan 28, 2013 • 6:00 pm No Comments Este artículo es una traducción de “Día 5: El contrato de configuraciones” de Jeff Blakenburg. Puedes encontrar aquí la versión original en inglés. […]

  5. Katrina Avatar
    Katrina

    These tutorials are amazing! Thank you so much for making them! There’s not much out there on Windows 8 Application programming, and whatever is out there is full of mumble jumble that I don’t understand. You guys put together a fabulous series here! It’s easy to understand and it goes step by step. I couldn’t have asked for better guidance.

  6. bryce Avatar
    bryce

    Where do I put the SettingsPane class and App_CommandsRequested method?

Leave a Reply to jeffblankenburg Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

%d bloggers like this: