| Comments

With the announcement of the Windows 8 Release Preview and matching Visual Studio 2012 RC I’m pleased to share some work that has been a result of my own personal app building, collaborating with some friends during their app building as well as porting some helpful projects that I’ve found helpful in my development.

Disclosure: At the time of this writing I do work for Microsoft, but this has been a personal effort from my own app development and during my own time (late nights and weekends).  I am not able to upload apps to the store at this time to share apps that I’ve written and receive no preferential treatment as a Microsoft employee.

Introducing Callisto, a toolkit of sorts for XAML Metro style apps.  When starting my own app building for the Consumer Preview, I realized there were some experiences and common things that I wanted to implement that weren’t existing controls in a way that I could easily re-use my efforts across app to app that I was building.  The foundation building blocks in the platform were there of course, as was a few existing Open Source projects that I could leverage (yay Open Source!).  I refactored the combination of these things into a single toolkit that I’ve been using for my apps.

Kitchen Sink?

My approach has been mostly pragmatic for me.  This was extracted out of app needs versus being designed as a toolkit from the beginning.  As such, it might feel like a ‘kitchen sink’ approach as there are things that you may never use.  For me, I wanted one thing I could add to my project and get all the goodness that I desired.  This is what led to a single project/toolkit rather than any modular approach.  For example, I originally had included the sqlite-net project in mine because I didn’t want to keep adding it to each project I was using the SQLite database engine.  This is one that I’ve removed since the changes I needed were contributed back to the project and I’ve wrapped them up in a nice easy NuGet package for that portion.

What is it?

Well, it is a toolkit!  It is a combination of some helper libraries as well as some controls.  Some original, some contributed, some ports from existing toolkits.  If you look at the project page you’ll see that it currently has:

  • Helpers: some attached property helpers for web content bindings, converters (i.e., for time relativeness)
  • Extensions: Tilt effect and some helpers for doing some things like OAuth 1.0 (adapted from RestSharp)
  • Controls: Flyout, SettingsFlyout, Menu, LiveTile

Menu flyout example

sample menu flyout from an AppBar

And more to come as I have time.  I’ve had the help of some folks in the community as well as being able to draw off things like the Silverlight Toolkit for some inspiration and some code as well! 

Settings flyout sample

sample settings flyout

The source project comes with a little crappy sample app that I’ve been using as my UI test harness. 

I fully plan to clean this up to a better sample app, but it serves a simple purpose for now.  You can see specific uses in that sample app for some of the controls.  Otherwise feel free to email me directly for some help and I’ll try to point you in the right direction.

How do I get it?

In addition to the source for those who would want that, you can get it in 2 ways: via NuGet or via the Visual Studio Gallery.  Incidentally you can install it both of these ways from within Visual Studio 2012 Express itself!  If using the gallery VSIX installer, then the toolkit will be available for you to use across multiple projects.  The NuGet approach is per-project (as it is with any NuGet package).  After installing the VSIX – if you use that approach – simply choose Add Reference in your project and navigate to the Windows…Extensions section and you’ll see it there.  It is implemented as an Extension SDK for Visual Studio.

Live tile sample

sample live tile (as best you can show in a static screenshot – imagine animation :-))

I plan on submitting regular updates as I refine things, fix bugs and add new controls.  Using the NuGet or VSIX approach for installing will help you keep updated as you’ll receive notifications of updates as long as you are using Visual Studio.

I found an issue/have an idea

Great, I’m sure there are some.  Again, it has been a few folks on our spare time working on this.  Please feel free to log a bug so that we can track the request.  The only place to log a bug is the Issues link on the project page.  No other mechanism will be a good feedback mechanism.

Alternatively, it is Open Source, so feel free to fork and fix.  Ideally you’d contribute your fix back to the project…we’d appreciate it.

Summary

At present the toolkit is for managed code Metro style apps only.  This isn’t because I don’t like C++ developers, but rather that this has been an extraction from my own app building and not designed from the start as any WinRT toolkit.

NOTE: There are a lot of things out there calling themselves WinRT toolkits for XAML.  So far I’ve actually seen none of them that are WinRT, but all are just regular .NET class libraries…just like Callisto.  These are all going to be restricted to use within a managed code XAML app.  If I can get assistance translating this all to WinRT native code, then I could easily see this being more valuable to others.

There are a lot of great APIs in WinRT available to developers.  The SDK samples also provide some helpful code for app developers as well you should ensure you look at (if you are doing ANYTHING with tiles, you should look at the Tiles SDK sample and pay attention to NotificationExtensions).  I hope that Callisto helps you as well in some small areas.

Hope this helps!

| Comments

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