×

First time here?

You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting!

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


This work is licensed under a Creative Commons Attribution By license.


3/7/2012 9:57 AM | # re: Building a good app settings experience in XAML
This is super helpful. Keep 'em coming! I have a change request though: when Popup.IsLightDismissEnabled=true, it should do the work of closing itself when the window is deactivated. That would remove a bunch of the boilerplate code here and match the dismiss behavior of AppBar.
3/7/2012 10:54 AM | # re: Building a good app settings experience in XAML
Another request: I'd like to make settings pane slide away (instead of just disappear) when dismissed like it does in the 1st party apps. Is this possible with LightDismiss? Looked at EdgeUIThemeTransition but it only supports top/bottom
3/10/2012 9:12 PM | # re: Building a good app settings experience in XAML
@Robert - re: windows deactivated, I agree and I've logged a bug on the team for consideration. Re: EdgeUIThemeTransition...agreed here as well and I have a bug for consideration there as well :-)
Gravatar
3/25/2012 7:00 PM | # re: Building a good app settings experience in XAML
Hey Tim, ran into an interesting scenario. I wanted to drop the Windows Live SignIn button onto a settings pane. However, when you put the button onto the pane, the pane opens and then immediately closes. I was using the sample from blogs.msdn.com/....

Any idea if this is possible, or is this a bug in the current build?
3/26/2012 2:28 PM | # re: Building a good app settings experience in XAML
@Bob - yes this is because the Live ID sign-in window actually de-activates the current app window...and the code above suggests to listen for de-activate to ensure the same behavior as the other flyouts in the system. In order to do this with Live SDK you would have to manage some flag and know that you are in the sign-in process and not close the panel if that is the desired experience for your app.
3/30/2012 5:25 AM | # re: Building a good app settings experience in XAML
Hi Tim, I've stumbled upon an interesting scenario which I bet is a bug in some sense.

If your BlankPage.xaml Content element is empty (even though you are vertically and horizontally stretching it across the page) and use the IsLightDismissedEnable propery you will get an AccessViolationException when trying to Close the Popup, as long as the Popup have actual content (such as an UserControl or similar).

Without very thorough examination it appears your page needs to have a UIElement which responds to input (such as a button), a simple TextBlock simply wont fix it...
4/2/2012 7:23 AM | # re: Building a good app settings experience in XAML
Hi,
If there is no clickable object on the page IsLightDismissEnabled causes AccessViolationException, so be sure to have a button on the page...
4/2/2012 4:38 PM | # re: Building a good app settings experience in XAML
@Johan/uesendir - while I am scratching my head thinking of a real app that would have no input controls...I just took a look at this on current bits and it works. My blank page has only a textblock and the settings (popup) comes out and dismisses on touch/click fine.
4/25/2012 9:14 AM | # re: Building a good app settings experience in XAML
Hi Tim! I use the same code (found somewhere on MSDN) but I can't get binding to work on the user control. The getter is never called on my view model. I wonder if binding does not occur because the user control is instantiated in code behind... Any idea?

Thanks a lot!
Fabian
4/25/2012 9:26 AM | # re: Building a good app settings experience in XAML
@Fabian - it is possible there is an issue with Binding for 2 reasons...first, this is effectively a Popup that isn't rooted, so the DataContext isn't being cascaded to the Popup, it would need to be explicitly set. Second, there are some known issues with Popup and DataContext even after that fact :-) -- although I don't think this would hit that area. If you have a small repro it would be cool to verify it.
4/25/2012 9:37 AM | # re: Building a good app settings experience in XAML
In my application, I set the DataContext to be bound to a ViewModelLocator but I tried something simpler in a test application: setting the DataContext in the constructor of the SimpleSettingsNarrow control and binding the ToggleSwitch text property.

See code here: http://pastebin.com/vMtnU4Zs

Thanks for your help,
Fabian
5/11/2012 10:40 AM | # re: Building a good app settings experience in XAML
Hey thanks Tim,
This was very helpful! One interesting bug I found is my page has a webView control which can't be drawn on for some reason. So my settings bar looks horrid.

So I have to set visibility to collapsed on my webview when I bring up settings.

thanks,
Sam
5/11/2012 10:49 AM | # re: Building a good app settings experience in XAML
@Sam - yes, this is an airspace issue with WebView. Setting it to Collapsed *or* using WebView brush and switching it out are options to overcome this.
5/29/2012 11:24 AM | # Option to change the background color of default SettingsPane
Hi,
Can you please tell me how to change the default background color of Settings Pane(Not custom Settings Pane )
5/29/2012 2:04 PM | # re: Building a good app settings experience in XAML
@Rahna - you cannot change the system provided settings pane (the first one) as that is based on the user's preferences for the OS.
6/5/2012 2:24 PM | # re: Building a good app settings experience in XAML
maaan, i have been waiting for this for a looooooooong time, really thank you
you have no idea
6/5/2012 6:30 PM | # re: Building a good app settings experience in XAML
For developers of large programs there is a lot missing in Metro.
I had a brief go at Metro with direct2d and the app that is default was a pig to get working for a simple plotting program. It feels a bit like Microsoft are making it hard deliberately.
Gravatar
6/7/2012 9:09 PM | # re: Building a good app settings experience in XAML
Hi Tim,

Great example and I have managed to use it to implement my own settings.

I have a problem when my settings popup has a text box near the bottom. When I tap on this text box, the on-screen keyboard.

Now the actual canvas elements of the "page" (the other xaml behind the settings popup) does move up fine, but the settings popup itself stays in place.

Any ideas how to handle this?
6/7/2012 9:15 PM | # re: Building a good app settings experience in XAML
@RA - yes this is one of the nuances of Popup. In order for the input to move automatically the popup must have a parent in the visual tree. If you can accomplish that, then it will do it for you.
6/18/2012 2:56 AM | # re: Building a good app settings experience in XAML
hi, this is very helpful, thanks. but I have a question.
How can I show the SettingPane with My custom Panel instead of default one.
such as I add a SettingsCommand name " login" , everytime I need to click the login button in SettingPane then can show the Login Panel.
I want to click the button in appbar then show the login panel in SettingPane. How should I do?
6/18/2012 4:55 AM | # re: Building a good app settings experience in XAML
I have already know how to to , thank you all the same :)
6/19/2012 9:50 AM | # re: Building a good app settings experience in XAML
We have implemented a Settings panel for our app, based on this example.

When the settings button is clicked, we resize our controls (using the ViewStateManager) so that a WebView control doesn’t bleed through the child popup window used for the custom settings. When the child popup window is closed, the controls are reset back to their original states.

The problem occurs if the top level SettingsPane is dismissed before the child popup is created, our main window does not receive any Resize, Activation or other notices that would allow us to reset to the default ViewState. The Resize and Activation events do not occur as when the child popup is activated and closed.

I also tried adding a handler on the PointerPressed event on the outermost grid, but it seems like the SettingsPane captures this event, interprets this as the light-dismiss without forwarding to the event to the application. Again, the PointerPressed event is raised once the child popup is activated.

The question is - is there any event or other way to handle the case when SettingsPane is closed directly to allow our app to reset to the default ViewState.

ps. We saw this originally on the Consumer Preview with the VS2011 Beta, but now see it on the Release Preview with VS2012 RC. Also, I've verified that the Callisto sample exhibits the same behavior on the RP with VS2012 RC.
7/6/2012 12:51 PM | # re: Building a good app settings experience in XAML
Hi Tim,
I used this example, and it is working great. The only issue I am facing is when e switch between pages, it keep adding SettingsCommand, and shows multiple instances for same command. I do have OnPopupClosed event handler with Window.Current.Activated -= OnWindowActivated;
Any suggestion why it could be happening?
7/26/2012 5:07 AM | # re: Building a good app settings experience in XAML
Hi all ,
When the PopUp panel is shown and disappeared, How I can add a slider animation
8/3/2012 4:12 AM | # re: Building a good app settings experience in XAML
Hi Tim,

I have the same issue as mentioned by Kamal.
Any idea why its happening?
9/5/2012 3:04 AM | # re: Building a good app settings experience in XAML
Hi,
If there is no clickable object on the page IsLightDismissEnabled causes AccessViolationException, so be sure to have a button on the page...
9/26/2012 12:07 AM | # re: Building a good app settings experience in XAML
Hi, timheuer,
I encounter a problem that my custom app setting will just disappear while I click somewhere out of the setting pane. How can I make my setting pane slide away just like the effect of Permissions setting pane provided by MS?
10/2/2012 1:36 AM | # re: Building a good app settings experience in XAML
Thanks! You saved me the time to figuring out the right size of the popup and how to use it as Settings menu.

11/15/2012 8:25 AM | # re: Building a good app settings experience in XAML
Maybe I am missing something but how are you unsubscribing from CommandsRequested event. If you don't unsubscribe you will not only leak the page object but will also attach multiple options from past pages every time the Settings charm is opened.
Gravatar
2/7/2013 11:06 AM | # re: Building a good app settings experience in XAML
To expand on Bob's question about Windows Live Signin...does it makes sense to have things like Signin/Login in the SettingsPane? I'm thinking about putting Login and Payment Method (add,remove,update Credit Cards) in the SettingsPane, but it seems like an awkward experience.

 
Please add 5 and 2 and type the answer here:

DISCLAIMER:

The opinions/content expressed on this blog are provided "ASIS" with no warranties and are my own personal opinions/content (unless otherwise noted) and do not represent my employer's view in any way.