Microsoft Advertising logoToday, the Microsoft Advertising team announced an update to their AdCenter SDK to include support for monetizing your Metro style apps.

In a blog post announcing the update, Ian notes that if you were using the previous SDK that there have been breaking changes and to use the updated SDK.  This update includes support for XAML applications and adding the ad units couldn’t be easier.  After installing their SDK (which was developed using the same distribution concepts in my post about creating a distributable custom control previous post), you will be able to use Add Reference in Visual Studio, navigate to the Windows/Extensions area and add the SDK.  After that it is as simple as adding the control in your project:

   1: <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
   2:     <Border Background="Red" VerticalAlignment="Bottom">
   3:         <ads:AdControl xmlns:ads="using:Microsoft.Advertising.WinRT.UI" 
   4:                        VerticalAlignment="Bottom" Width="728" Height="90" 
   5:                        AdUnitId="YOUR_AD_UNIT_ID" 
   6:                        ApplicationId="YOUR_APPLICATION_ID" />
   7:     </Border>
   8: </Grid>

Now you do, of course, have to have a pubCenter account and create the ad units beforehand in order for this to work, but that setup time didn’t take long at all.

You may have some time for your own ad units to be provisioned and start serving ads, but the ad team created some test values you can use to see how things all work.  Download the Ads SDK today!

Hope this helps!

At //build one of the surprising immediate things I heard about was folks wanting to build custom controls right away.  I knew that would happen, but not so quick on something so new (WinRT).  The XAML platform did not have good support for building custom controls in the Developer Preview but now that the Consumer Preview for Windows 8 and Visual Studio 11 Beta are out, there is much better support.  There are two key things when thinking about custom controls: 1) building it and 2) making it consumable by developers (even if those developers are your own company).  I’ll try to articulate the methods of both here.

Defining custom versus user control

There is usually some debate in the XAML community about the definition of a custom control.  For the purposes of this discussion I define a custom control as a control that provides a generic.xaml, can be styled/templated and is usually encapsulated in its own assembly which can then be distributed.  A custom control can contain user controls, but generally speaking does not.  A typical user control scenario is one that lives within your project and not meant to be consumed by anyone outside your project.

This definition is the same whether we are talking about C++, C# or Visual Basic.  Everything below applies to all languages.

Creating the custom control

The fundamentals of a custom control are that it is a class and it provides it’s own template/style.  This style/template definition usually lives in a file located at themes/generic.xaml.  This is the same pattern that has existed in other XAML implementations like WPF, Silverlight and Windows Phone.  The pattern is no different for Metro style apps in this regard.

The creation of the most basic custom control is very simple.  A Windows SDK sample for XAML User and Custom Controls is available for you to download for the quick review and core concept.  My intent here is to take that a step further for the end-to-end implementation if I were a control vendor.  Let’s first create our control.  For our purposes we will create a control that shows an Image and allows you to specify some Text for the label.  The label, however, will be prepended with some text that comes from string resources.

In Visual Studio we will create a class library project first.

NOTE: You can create a C#/VB Class Library and keep it managed, or convert it to a WinRT component.  You may also create this in C++ using the WinRT Component project type.  Again, these concepts are the same, the syntax will be obviously slightly different for C++ and managed code.

Once you create the class library (I called mine SimpleCustomControl and deleted the initial Class1.cs file that was created), add an item to the project.  You can do this via right-clicking on the project and choosing add item.  You will be presented with a few options, but the important one is Templated Control.

Add Item dialog

Watch was this does to your project as it will do 2 things:

  • Create a new class
  • Add a Themes folder and place a ResourceDictionary called generic.xaml in that folder

The themes/generic.xaml is very important if you use the DefaultStyleKey concept in your class.  This is very much a convention-based approach.  The contents of the class is very simple at this point, with the sole constructor and the DefaultStyleKey wired up:

   1: namespace SimpleCustomControl
   2: {
   3:     public sealed class LabeledImage : Control
   4:     {
   5:         public LabeledImage()
   6:         {
   7:             this.DefaultStyleKey = typeof(LabeledImage);
   8:         }
   9:     }
  10: }

This maps to the generic.xaml definition of our control.  Let’s modify our ControlTemplate in generic.xaml to be a little more than just a border:

   1: <Style TargetType="local:LabeledImage">
   2:     <Setter Property="Template">
   3:         <Setter.Value>
   4:             <ControlTemplate TargetType="local:LabeledImage">
   5:                 <Border Background="LightBlue" BorderBrush="Black" BorderThickness="2" 
   6:                         HorizontalAlignment="Center" Width="140" Height="150">
   7:                     <StackPanel HorizontalAlignment="Center">
   8:                         <Image Stretch="Uniform" Width="100" Height="100" 
   9:                                Source="{TemplateBinding ImagePath}" Margin="5" />
  10:                         <TextBlock TextAlignment="Center" FontFamily="Segoe UI" FontWeight="Light" 
  11:                                    FontSize="26.667" Foreground="Black" x:Name="LabelHeader" />
  12:                         <TextBlock TextAlignment="Center" 
  13:                                    Text="{TemplateBinding Label}" FontFamily="Seqoe UI" FontWeight="Light" 
  14:                                    FontSize="26.667" Foreground="Black" />
  15:                     </StackPanel>
  16:                 </Border>
  17:             </ControlTemplate>
  18:         </Setter.Value>
  19:     </Setter>
  20: </Style>

Now we have a place for an Image, LabelHeader and a Label.  Notice that we have {TemplatBinding} statements there.  This is how the template binds (duh) to values provided to the control.  So our ControlTemplate is expecting these properties to exist on our control.  We will create these as DependencyProperty types so we can use them in Binding, change notification, etc.  In Visual Studio we can make re-use out of the ‘propdp’ code snippet that exists for WPF.  It is slightly different in the last argument, but it will definitely save you a lot of typing.  We’ll create 2 DependencyProperties like this in our LabeledImage.cs file:

   1: public ImageSource ImagePath
   2: {
   3:     get { return (ImageSource)GetValue(ImagePathProperty); }
   4:     set { SetValue(ImagePathProperty, value); }
   5: }
   6:  
   7: public static readonly DependencyProperty ImagePathProperty =
   8:     DependencyProperty.Register("ImagePath", typeof(ImageSource), typeof(LabeledImage), new PropertyMetadata(null));
   9:  
  10: public string Label
  11: {
  12:     get { return (string)GetValue(LabelProperty); }
  13:     set { SetValue(LabelProperty, value); }
  14: }
  15:  
  16: public static readonly DependencyProperty LabelProperty =
  17:     DependencyProperty.Register("Label", typeof(string), typeof(LabeledImage), new PropertyMetadata(null));

We also had that LabelHeader property.  This is going to be a value coming from a string resource that may be localized at some point.  In our library add a folder called “en” and then within that, using the Add Item dialog in VS, add a Resources.resw file.  Within that Resources.resw file add a name/value pair of name=LabelHeader.Text and value=This is an image of a… and you can save/close the file.

Now back to our class file we are going to set the value of our TextBlock by overriding our template rendering, grabbing a reference to that TextBlock and setting the value from our string resource.

   1: protected override void OnApplyTemplate()
   2: {
   3:     base.OnApplyTemplate();
   4:  
   5:     TextBlock tb = GetTemplateChild("LabelHeader") as TextBlock;
   6:     tb.Text = new ResourceLoader("SimpleCustomControl/Resources/LabelHeader").GetString("Text");
   7: }

Now, I’m showing this way, because it is pretty verbose and there is an easier way…but you wouldn’t know it is easier unless you saw the harder way right?

First it is important to understand how these resources are indexed.  You’ll notice that I’m using a ResourceLoader class to map to what looks like {component}/{resw-file-name}/{property} which is effectively right.  When you create a resw file, at compile-time these get built into a PRI file.  This post isn’t about this whole resource loading process, but you should definitely understand this a bit.  Basically for a control creator perspective you need to understand that your string resources (and file-based resources) live in a ResourceMap that is the name of your component.

NOTE: An easy way to look at this resource indexing is to use the makepri.exe tool installed with VS.  From a VS command prompt navigate to your build output and you should see a resources.pri file.  Call makepri.exe dump and you’ll get an XML representation of that file you can look at.  Knowing that structure is very helpful.

I said there was an easier way to get that string though.  First remove the OnApplyTemplate override completely…we don’t need it for this control anymore.  Now in generic.xaml change the x:Name=”LabelHeader” to the following:

   1: <Style TargetType="local:LabeledImage">
   2: ...
   3:     <TextBlock TextAlignment="Center" FontFamily="Segoe UI" FontWeight="Light" 
   4:                FontSize="26.667" Foreground="Black" 
   5:                 x:Uid="/SimpleCustomControl/Resources/LabelHeader" />
   6: ...
   7: </Style>

This will use the XAML parser way of getting the string resource (note the ResourceMap is still in the x:Uid value).  Using the ResourceMap prefix is necessary when using this method as a custom control vendor.

We are done.  Our control is complete.

Consuming the control from an application

We can quickly test our control by adding a new Metro style app to our project.  Once we do this, make that the startup project and add a project reference to our control library.  Then in the default page for our app (BlankPage or MainPage depending on your template choice), add an xmlns to the top and then consume the control:

   1: <Page
   2:     x:Class="Application1.BlankPage"
   3:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   4:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   5:     xmlns:local="using:Application1"
   6:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   7:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   8:     xmlns:controls="using:SimpleCustomControl"
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
  12:         <controls:LabeledImage ImagePath="Assets/110Orange.png" Label="Orange" />
  13:     </Grid>
  14: </Page>

See how the ImagePath and Label are used here?  In more advanced scenarios we can bind values from our view model or other ways.  When rendered the control will show like this:

Custom control rendered

This is great…but also what we call a “project-to-project” (P2P) reference.  As a control vendor we want to distribute our control, not our source primarily.  So we need to package this up.  There are two ways you can do this.

Package your control as an Extension SDK

One of the new methods for distributing Metro style controls in VS11 is via Extension SDKs, also sometimes referred to as non-Framework SDKs.  Extension SDKs are machine-wide and available to all projects once installed.  They can be distributed via the Visual Studio gallery and using the VSIX mechanism…which allows for update notification in Visual Studio.  There are a few intricacies that you can configure your Extension SDK but for most it will get down to three things:

  • Describing your SDK and what it supports
  • Including the binary that projects need to reference
  • Including any assets/files that the control relies on to render

In examining our sample above we have a few things that map to this:

  • Describing – our sample is a C# custom control so it will only work with managed Metro style apps, we will need to describe this in our SDK
  • Binary – we have one binary: SimpleCustomControl.dll
  • Redistributables – we have a generic.xaml and a PRI file with our string resources

The last part (redist) probably is making some existing XAML control developers scratch their heads.  Why isn’t the generic.xaml embedded is what you are likely asking yourself.  In Metro style apps, XAML assets are not embedded but rather exist as “loose file” assets for your control.  This is why it is critical for getting the distribution model correct so that the runtime knows where to get the definitions for everything.

NOTE: This is a default method.  You can, of course, use other techniques to get your assets into your binary either via string constants, other embedding techniques, etc.  In doing so, however, you will now be managing all those extractions yourself rather than being able to rely on the resource APIs for Metro style apps.

The first thing we want to do is understand the structure of an SDK.  These live in %ProgramFiles%\Microsoft SDKs\Windows\v8.0\Extension SDKs directory on disk.  Within there you will have your own folder, version and then the layout of your SDK, as described by your manifest.  Here is what our manifest (SDKManifest.xml) would look like for our control:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <FileList 
   3:   DisplayName="Simple Custom Control" 
   4:   ProductFamilyName="Simple Controls"
   5:   MinVSVersion="11.0" 
   6:   MinToolsVersion="4.0" 
   7:   CopyRedistToSubDirectory="SimpleCustomControl"
   8:   AppliesTo="WindowsAppContainer+WindowsXAML+Managed"
  10:   MoreInfo="http://timheuer.com/blog/">
  11:   <File Reference="SimpleCustomControl.dll">
  12:     <ContainsControls>True</ContainsControls>
  13:   </File>
  14: </FileList>

We are describing the display information as well as some key data:

  • Display data – the title that will show up in Add Reference
  • CopyRedistToSubdirectory – this would be the name of your component
  • AppliesTo – what I support; in this I’m saying managed, XAML, Metro style apps
  • <File> – these are the files that describe components in my SDK (not their loose assets)

Now to create the structure.  When you build the DLL your output will give you this:

Build output

We need to create the following structure that will live under the Extension SDK folder listed above:

%ProgramFiles%\Microsoft SDKs\Windows\v8.0\Extension SDKs\

--SimpleCustomControl

----1.0

------SDKManifest.xml (the file above)

------References\CommonConfiguration\neutral\SimpleCustomControl.dll

------Redist\CommonConfiguration\neutral\SimpleCustomControl.pri

------Redist\CommonConfiguration\neutral\Themes\generic.xaml

Notice the References and Redist folders.  By placing these in that structure, the project will know what it needs to get type information (References) and then during running/deployment what it needs to package (Redist) and where it puts it (CopyRedistToSubdirectory).  Put this layout in the directory and then when you choose add reference on a project you will see your option:

Add reference dialog

There are other configuration options for the SDKManifest that you can use and the required reading is the Extension SDK section in this MSDN article: How to: Create a Software Development Kit.

The next step for an Extension SDK is to really package it up nicely.  You probably don’t want your users copy directories around all the time…and what about updates as well!  Using the Visual Studio VSIX structure for this really makes it easy to do.

There are tools for Visual Studio to allow you to create a VSIX package.  This requires the Visual Studio extensibility SDK to be installed and using Visual Studio professional or higher.  Once you do that you can create a VSIX package and you will see the VSIX manifest designer.  On the Install Targets tab you will choose Extension SDK:

VSIX Install Targets

We then re-create the layout structure in the VSIX project and add the Assets to the manifest.  The result in the IDE looks something like this:

VSIX Manifest Assets

Now when we build we will get a VSIX installer that we can upload to the Visual Studio Gallery or distribute to our customers.

NOTE: Uploading the to Visual Studio Gallery has benefits in that once installed, any update you put in the gallery will provide notifications to the Visual Studio user than an update exists.  This is done via the unique Product ID value in your manifest, so choose that value accordingly and don’t change it if you want this capability.

When a user gets the VSIX, they double-click it and see the installer:

VSIX Installer

And then they can use it as normally in Add Reference just like described above.  Additional details on other VSIX deployment configurations can be found here: VSIX Deployment.

Once you have your VSIX you can upload to the Visual Studio Gallery and make it discoverable for users from within Visual Studio.  Remember that this method of Extension SDK is machine-wide which is in contrast to the second method described next.

Package your control as a NuGet Package

The other option you have is to package up your control via a NuGet package.  NuGet packages apply to the project and not the machine, but have the flexibility of not having to have anything installed and can travel their dependencies with the project.  NuGet packages are another type of package that has a manifest that describes what the content does. 

For Metro style XAML controls you will have to do a few things differently currently with the NuGet package you create.  NuGet packages are based on nuspec files, which is basically a manifest describing where to get/put things in the package.  You can also use the NuGet Package Explorer for a GUI way of reading/creating new packages.  If you are unfamiliar with the nuspec format, using the package explorer will help you get a package created quickly. 

NuGet is one area where there actually are current differences in C++ or managed code.  Right now NuGet only supports managed code projects and not C++.  I’m sure this may change in the future, but as of right now this applies only to managed code.  For our control above here is what my nuspec file looks like:

   1: <?xml version="1.0"?>
   2: <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
   3:   <metadata>
   4:     <version>1.0.0</version>
   5:     <authors>Tim Heuer</authors>
   6:     <owners />
   7:     <id>SimpleCustomControl</id>
   8:     <title />
   9:     <requireLicenseAcceptance>false</requireLicenseAcceptance>
  10:     <description>A simple custom control for Metro style apps</description>
  11:   </metadata>
  12:   <files>
  13:     <file src="SimpleCustomControl\bin\Debug\Themes\Generic.xaml" target="lib\winrt\SimpleCustomControl\Themes\Generic.xaml" />
  14:     <file src="SimpleCustomControl\bin\Debug\SimpleCustomControl.dll" target="lib\winrt\SimpleCustomControl.dll" />
  15:     <file src="SimpleCustomControl\bin\Debug\SimpleCustomControl.pri" target="lib\winrt\SimpleCustomControl.pri" />
  16:   </files>
  17: </package>

This assumes that the binaries being referenced here are all relative to the nuspec file.  Notice how all the files go into the lib\winrt folder and that we essentially re-create that SDK layout in our package as well.

Now when I build this with nuget.exe I get a package output.  In Visual Studio (with NuGet installed) I can now right-click on a project and choose Manage NuGet Packages and browse the library of packages.  In testing out my package, I create a custom library (you do this via the Settings option when you are in the Manage NuGet Packages dialog) and just point it to the folder where my nupkg file was created:

Manage NuGet Packages dialog

When the package is selected, the reference is added to my project and during build, all the right pieces are put in my APPX package where they need to go.  Once the reference is there I build and run my project and the control renders as expected!

What about the design-time experience?

All of the methods above will allow you to view your control on the XAML design surface in Visual Studio as well.  In the Extension SDK method there is actually additional affordances for you to provide additional design-time assemblies/resources to make that experience even better.  Custom control developers for XAML know about this .Design.dll that is created for their projects that can improve the design-time experience for UI controls.  I highly encourage you to do that if you are creating a control that is for wide distribution and not just yourself or your small group of friends.

Summary

Wow this felt like a long post…thanks for reading this far!  I think developing custom controls is a great way to encapsulate specific UI and behavior you want in your application.  XAML has a great ecosystem of control vendors and I fully expect them to produce controls for Metro style apps as well.  Hopefully these techniques of packaging them up for distribution will help us all take advantage of them.

I also think that creating an Extension SDK *and* a NuGet package are the best ways of thinking about it as a producer.  This enables your consumers to have the greatest flexibility in how they want to consume your control.  Creating these distribution mechanisms may seem cumbersome at first (and there are some places where Visual Studio can improve the experience of creating/managing these manifests), but once you understand the core layout that is required for a Metro style XAML control and the fact that you now have “loose files” to consider it really becomes pretty streamlined and you can automate the creation of these pretty quickly in your build systems.

Be sure to check out these resources again:

Here is the solution for the project I walked through above: SimpleCustomControl.zip

Hope this helps!

Today the Bing team announced the release of their WinRT Bing Maps control (BETA) for XAML applications.  First the goods:

If you are familiar with the Silverlight control, it is similar in nature to how you would use it in your XAML Metro style app.  Here’s some helpful tips that are in the docs but just wanted to elevate them because we have a tendency not to read docs :-).

Installing

Installing is simple for Visual Studio.  Download the VSIX file and double-click it.  If you have both Express and Ultimate installed it will prompt you to install it for both installations.  That’s it…you are done.  If you had VS running while you did this, it would be a good idea to restart VS.

Creating a .NET XAML application with maps

Once you restart VS, you can create a new C# Metro style application.  Once you have this, just right click on the project and choose Add Reference and then navigate to the Windows\Extensions section and you will see Bing Maps:

Bing Maps Reference

When you do this you will also want to add a reference to the VCLibs Extension at this time.  Why?  Well, the Map control is a native control.  Adding the VCLibs dependency at this time will add the necessary information in your app’s package manifest noting the dependency and it will install any required package dependencies from the store when your user’s install it.

If you compile your application immediately you will notice an exception during build:

   1: 1>------ Build started: Project: Application17, Configuration: Debug Any CPU ------
   2: 1>C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1667,5): error MSB3774: Could not find SDK "Microsoft.VCLibs, Version=11.0".
   3: 1>C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1667,5): error MSB3778: "APPX" attributes were found in the SDK manifest file however none of the attributes matched the targeted configuration and architecture and no "APPX" attribute without configuration and architecture could be found. If an appx is required then the project will fail at runtime.
   4: ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

This is because by default the managed applications are “AnyCPU” configuration and the native control doesn’t have that configuration.  Change your app to be either x86 or amd64 and your build will succeed.  This means that yes, you will want to create multiple architecture-specific packages for your app.  The good thing is during package creation, the tools in Visual Studio make this easy for you.

Creating a C++ XAML application with maps

For C++ the step is to just reference the Bing Maps extension SDK and you are done.  C++ projects are always architecture-specific so you don’t have the AnyCPU situation here.

Using the Map control

You’ll need to get set up with an API key, which the getting started docs inform you about.  Once you have that you are ready to use the control.  I’m a fan of putting the API key in my App.xaml as a resource:

   1: <Application.Resources>
   2:     <ResourceDictionary>
   3:         <ResourceDictionary.MergedDictionaries>
   4:             <ResourceDictionary Source="Common/StandardStyles.xaml"/>
   5:         </ResourceDictionary.MergedDictionaries>
   6:         <x:String x:Key="BingMapsApiKey">YOUR KEY HERE</x:String>
   7:     </ResourceDictionary>
   8: </Application.Resources>

And then in my Map control I can just refer to it:

   1: <Page
   2:     x:Class="Application17.BlankPage"
   3:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   4:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   5:     xmlns:local="using:Application17"
   6:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   7:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   8:     xmlns:bing="using:Bing.Maps"
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
  12:         <bing:Map x:Name="MyMap" Width="640" Height="480" 
  13:             Credentials="{StaticResource BingMapsApiKey}" />
  14:     </Grid>
  15: </Page>

Once I have those pieces in place, I’m done and can run my app and get full map interactivity.  Notice the xmlns declaration in my Page with the “using:Bing.Maps” notation.  Now when I run:

Bing Maps

I can quickly add location to my app by setting the capability in the Package.appxmanifest and then wiring up the map to center on my current location…

   1: async protected override void OnNavigatedTo(NavigationEventArgs e)
   2: {
   3:     Geolocator geo = new Geolocator();
   4:     geo.DesiredAccuracy = PositionAccuracy.Default;
   5:     var currentPosition = await geo.GetGeopositionAsync();
   6:  
   7:     Location loc = new Location() { Latitude = currentPosition.Coordinate.Latitude, 
   8:         Longitude = currentPosition.Coordinate.Longitude };
   9:  
  10:     MyMap.SetView(
  11:         loc, // location
  12:         13, // zoom level
  13:         true); //show animations)
  14:  
  15: }

I’m excited about what the Bing team has done here and you should go grab it, read the docs and start incorporating location visualization into your Metro style XAML apps today!

Hope this helps!

So you’ve started to kick the tires of the Windows 8 Consumer Preview and now you are building an app.  You’ve read all the UX design guidelines and started looking at some great apps on the store.   Perhaps you’ve also viewed the online documentation and some samples?  And you’ve likely read about the contract implementations and other charms items like custom settings. 

UPDATE: Take a look at Callisto: a XAML toolkit which has a SettingsFlyout control

What is Settings?

When I refer to Settings here I’m referring to that consistent experience in Metro style apps when the user invokes the charms bar and chooses settings.  By default every application will respond to that Settings charm.  If you do nothing you will get the default experience that you may have seen:

Default Settings experience

The text items underneath your app title are referred to as commands.  Each application will always get the Permissions command.  When the user clicks this they will get some “about” information on your app (name, version, publisher) as well as the permissions the app has requested.  As an app developer, you have to do nothing to get this experience.  In addition to that the Settings pane shows some OS-level options like volume, Wi-Fi, brightness, etc. that the user can manipulate.  But you, my fellow app developer, can also implement custom settings options in your app.

The custom SettingsCommand

The first thing you have to do to customize your experience is implement a custom SettingsCommand.  These are implemented by first listening to when the SettingsPane will request if there are any additional commands for the current view.  Settings can be global if you have something like a “master” page setup in your XAML application, but can also be specific to a currently viewed XAML page.  It is not an either/or but a both.  I’ll leave the exercise up to you and your app on when you need which (or both).

First thing you have to do is listen for the event.  You would likely do this in your XAML view’s constructor:

   1: public BlankPage()
   2: {
   3:     this.InitializeComponent();
   4:  
   5:     _windowBounds = Window.Current.Bounds;
   6:  
   7:     Window.Current.SizeChanged += OnWindowSizeChanged;
   8:  
   9:     SettingsPane.GetForCurrentView().CommandsRequested += BlankPage_CommandsRequested;
  10: }

Notice the SettingsPane.GetForCurrentView().CommandsRequested event handler that I am using.  This will get triggered whenever the user invokes the Settings charm while on this view.  It is your opportunity to add more commands to that experience.  In your method for this you would create your new SettingsCommand and add them to the ApplicationCommands:

   1: void BlankPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
   2: {
   3:     ResourceLoader rl = new ResourceLoader();
   4:  
   5:     SettingsCommand cmd = new SettingsCommand("sample", 
   6:         rl.GetString("SoundOptionCommandText"), (x) =>
   7:         {
   8:             // more in a minute
   9:         });
  10:  
  11:     args.Request.ApplicationCommands.Add(cmd);
  12: }

You are able to add the text-based commands to the SettingsPane at this time.  The second argument I provided above will be the text that will display as the menu.  Notice how here I’m using ResourceLoader to get the string value for the text to be displayed.  This is a best practice to ensure you give your user’s the best experience.  Even though you may not localize now, setting this up in the beginning makes it way easier to just drop in localized strings and not have to change code.  The “SoundOptionCommandText” exists as a key/value pair in a file in my project located at en/Resources.resw.

Now that I have this enabled and my CommandsRequested wired up, when I invoke the charm while my app is running you see my new command:

Custom SettingsCommand

Yippee!  Your custom commands will show before the Permissions one.  The next step is to actually add something valuable to the user when they click on this new command…and that means some UI.

The custom Settings UI

When your user clicks your new shiny command you want them to see some shiny, but relevant UI.  If you were using HTML/JS you would use the WinJS.UI.SettingsFlyout control to do a lot of this for you.  There is a sample of this for comparison located in the Windows 8 developer samples.  In XAML there isn’t the literal ‘SettingsFlyout’ control equivalent, but a set of primitives for you to create the experience.  There are a few pieces you will need in place.

First I create a few member variable helpers to store some items away:

  • _windowBounds – this is the Rect of the current Window size.  I will need this for proper placement
  • _settingsWidth – The UX guidelines suggest either a 346 or 646 wide settings flyout
  • _settingsPopup – the Popup that will actually host my settings UI

The Popup is the important piece here.  It is the primitive that provides us with the “light dismiss” behavior that you see a lot in the Windows 8 experience.  This is where you have a menu/dialog and you simply tap away and it dismisses.  Popup.IsLightDismissEnabled gives us that functionality in our control that we will need in XAML.  Now let us go back to where we created our custom SettingsCommand and add back in the creation of our Popup and custom UI:

   1: SettingsCommand cmd = new SettingsCommand("sample", rl.GetString("SoundOptionCommandText"), (x) =>
   2: {
   3:     _settingsPopup = new Popup();
   4:     _settingsPopup.Closed += OnPopupClosed;
   5:     Window.Current.Activated += OnWindowActivated;
   6:     _settingsPopup.IsLightDismissEnabled = true;
   7:     _settingsPopup.Width = _settingsWidth;
   8:     _settingsPopup.Height = _windowBounds.Height;
   9:  
  10:     // more to come still
  11: });

Notice that we are creating the Popup, setting the width to the value specified in _settingsWidth and the height to whatever the current height of the active Window is at this time.  We are also listening to the Activated event on the Window to ensure that when our Window may be de-activated for something that a user may not have done via touch/mouse interaction (i.e., some other charm invocation, snapping an app, etc.) that we dismiss the Popup correctly.  here is the OnWindowActivated method definition:

   1: private void OnWindowActivated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
   2: {
   3:     if (e.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated)
   4:     {
   5:         _settingsPopup.IsOpen = false;
   6:     }
   7: }
   8:  
   9: void OnPopupClosed(object sender, object e)
  10: {
  11:     Window.Current.Activated -= OnWindowActivated;
  12: }

Notice we are also listening for the Popup.Closed event.  This is so that we can remove the OnWindowActivated method to avoid any reference leaks lying around.  Great, now let’s put some UI into our Popup.

For my example here I’m using a UserControl that I created to exhibit my settings needs.  Your use may vary and you may just need some simple things.  As we know in XAML there is more than one way to implement it in this flexible framework and this is just an example.  Going back to our custom SettingsCommand we now create an instance of my UserControl and set it as the Child of the Popup, setting appropriate Width/Height values as well:

   1: SettingsCommand cmd = new SettingsCommand("sample", rl.GetString("SoundOptionCommandText"), (x) =>
   2: {
   3:     _settingsPopup = new Popup();
   4:     _settingsPopup.Closed += OnPopupClosed;
   5:     Window.Current.Activated += OnWindowActivated;
   6:     _settingsPopup.IsLightDismissEnabled = true;
   7:     _settingsPopup.Width = _settingsWidth;
   8:     _settingsPopup.Height = _windowBounds.Height;
   9:  
  10:     SimpleSettingsNarrow mypane = new SimpleSettingsNarrow();
  11:     mypane.Width = _settingsWidth;                    
  12:     mypane.Height = _windowBounds.Height;
  13:  
  14:     _settingsPopup.Child = mypane;
  15:     _settingsPopup.SetValue(Canvas.LeftProperty, _windowBounds.Width - _settingsWidth);
  16:     _settingsPopup.SetValue(Canvas.TopProperty, 0);
  17:     _settingsPopup.IsOpen = true;
  18: });

Now when the user clicks the “Sound Options” they will see my custom UI:

Custom Settings UI

And if the user taps/clicks away from the dialog then it automatically dismisses itself.  You now have the fundamentals on how to create your custom UI for settings.

Some guiding principles

While this is simple to implement, there are some key guiding principles that make this key for your user’s experience.  First and foremost, this should be a consistent and predictable experience for your users.  Don’t get crazy with your implementation and stay within the UX design guidelines to ensure your app gives the user confidence when using it.  Additionally, here are some of my other tips.

Header Elements

You’ll notice above that the header of the custom UI is specific and contains a few elements.  The title should be clear (and again be ideally localized) in what the settings is doing.  The background color would match your app’s branding and likely be the same as the value of BackgroundColor in your app’s package manifest.  Putting your logo (use the same image you use for your SmallLogo setting in your package manifest) helps re-enforce this is the setting only for this app and not for the system.  Additionally providing a “back” button so the user can navigate back to the root SettingsPane and not have to invoke the charm again if they wanted to change other app settings.  In my example, the button simply just calls the SettingsPane APIs again to show it:

   1: private void MySettingsBackClicked(object sender, RoutedEventArgs e)
   2: {
   3:     if (this.Parent.GetType() == typeof(Popup))
   4:     {
   5:         ((Popup)this.Parent).IsOpen = false;
   6:     }
   7:     SettingsPane.Show();
   8: }

You may be curious to see the XAML used for my custom UI and I’ve included that in the download at the end here as not to take up viewing area here on the key areas.

Immediate Action

Unlike some modal dialog experiences, the Settings experience should create immediate change to your application.  Don’t put confirmation/save/cancel buttons in your UI but rather have the changes take effect immediately.  For instance in my sound example, if the user invokes the Settings charm, clicks/taps on my Sound Options and toggles the Sound Effects option on/off, then the sound should immediately turn on/off.  Now implementing this philosophy may change the way you create your custom UI and/or UserControl, but take that into account when designing.

Light Dismiss

This concept of light dismiss is about honoring the user’s action and not requiring interruption.  This is why we use the Popup.IsLightDismissEnabled option as we get this capability for free.  By using this if the user taps away to another part of the application or Window, then the Popup simply dismisses.  Don’t hang confirmation dialogs in there to block the user from doing what they want, but rather honor the context change for them.

Summary

The Windows platform has afforded us developers a lot of great APIs to create very predictable and consistent user experiences for the common things our apps will need.  Settings is one of those simple, yet effective places to create confidence in your application and a consistent Windows experience for your users.  Stick to the principles:

  • Set up custom commands that make sense for the context of the view and/or for the app as a whole
  • Create and show your UI according to the UX design guidelines
  • Have your settings immediately affect the application
  • Ensure that you use the dismiss model

Combine all these and you will be set.  Everything I talk about above is supported in XAML and WinRT.  My example is in C# because I’m most proficient in that language.  But this 100% equally applies in C++ as well and should be identical in practice.

You may be saying to yourself wouldn’t this make a great custom control?  Ah, stay tuned and subscribe here :-)!

Hope this helps!

Download Sample: download removed...see Callisto

An old colleague of mine and now HTML extraordinaire, Adam Kinney, just recently posted on his spelunking of some styling in both WinJS and XAML runtimes with regard to icons/buttons to use in a Metro style app and the AppBar.

Adam has two posts:

Basically what these do is define a set of styles, both in CSS and XAML, that map back to unicode values in the Segoe UI Symbol font.  This contains a set of glyphs that are well-suited for use within an AppBar.  As an example in WinJS you would use:

   1: <button data-win-control="WinJS.UI.AppBarCommand" 
   2:         data-win-options="{icon:'back', label:'Back'}"><button>

And in XAML you would use:

   1: <Button Style="{StaticResource PreviousAppBarButtonStyle}" />

One thing that Adam points out is that WinJS includes definitions for a LOT of styles while the included StandardStyles.xaml file (provided for you when you create a new project in Visual Studio) defines a much smaller subset.  When determining what styles to include in the XAML set, we opted for choosing the most common rather than to bloat the ResourceDictionary with things you may not use.

NOTE: Even within the provided one, you should always make it a best practice to REMOVE styles/templates that you aren’t using so the parser doesn’t have to worry about them.

Adam also notes that he likes the style of defining the WinJS ones a bit better as he mentions the XAML syntax feels heavy.  I commented on his blog that WinJS is doing a lot of work for him here that has already defined the style.  If WinJS didn’t exist, surely it would be ‘heavy’ in defining them.  I’m still not sure why the XAML one feels heavy (once you just assume that a definition has been made for you in the ResourceDictionary provided – especially when I look above, they basically both look the same…but I digress.

One thing that I wanted to point out was how the tools, Visual Studio and Blend, help make it way easy to choose and quickly visualize these styles on the design surface.  For HTML/JS apps you need to use Blend for this as VS doesn’t support this feature at this time.  When in Blend in your HTML/JS app you can open up the control palette and see a helper for AppBar Command Button:

Blend and AppBar Command Button

And this produces a generic button definition much like above:

   1: <button data-win-control="WinJS.UI.AppBarCommand" 
   2:         data-win-options="{label:'Button', type:'button'}"></button>

What you can’t do from now (that I could see) is quickly pick from a set of those data-win-options to choose which one you want…so you still have to know what the definition is that you want for the icon/label.  Let’s contrast that with the XAML experience with strongly-defined styles.  In VS or Blend I can use the resource picker to pick from a set of styles that apply to my control type, in this case button:

Blend for XAML AppBar Resources

I can quickly change and see the option on the design surface.  Now again, if you don’t need all these styles, then please delete what you aren’t using from your ResourceDictionary.

It is great that we have design-time implementations of these styles and of course I’m partial to the XAML one as more familiar to me.  Adam pointed out the discrepancy of not having all the styles defined.  As I note, you shouldn’t have defined what you don’t need, but in the spirit of adding value, here’s an updated StandardStyles.zip with all the 150 icons defined.

Hope this helps!