Home > Metro, Windows 8 > Windows 8 App Setttings flyout dialog

Windows 8 App Setttings flyout dialog

All Windows 8 app settings must be accessible through the same mechanism.
While in any app, the user must be able to enter the settings dialog through the settings charm. (Swipe from the right edge on a touch device or use WinKey+C)

The settings charm by default will display the generic settings dialog like this one on the left.

The user can follow links from this dialog to specific settings, which in turn will display another dialog.  This other dialogs will always lay on top of the current dialog,
so it seems, that they are replacing it.
The only difference is, that this other dialogs have a back button
on the top, which allows the user to go back to the initial settings page.

image image

Clicking on anything outside the settings dialog will close the dialog (light dismiss).

Sample dialog after clicking on "My Settings menu" entry

Adding a new menu entry to the default settings page

To add a settings dialog, the first step is to add a menu label to the default settings page.

For this the CommandsRequested event must be intercepted, e.g. by adding the hilighted line in the ctor of the Mainpage:

This will make sure, that the new settings menu label will be added to the settings pane, before the pane will be shown. 
The Microsoft UI style guide recommends to use either a 346 px or 646 px wide dialog for the settings flyout!

private double settingsWidth = 346; // should be 346 or 646 
private Popup settingsPopup;        // container for flyout
private Rect windowBounds;          // determine correct height
public MainPage() { this.InitializeComponent(); windowBounds = Window.Current.Bounds; SettingsPane.GetForCurrentView().CommandsRequested +=
SettingsOnCommandsRequested;
Window.Current.SizeChanged += OnWindowSizeChanged; } void OnWindowSizeChanged(object sender,
Windows.UI.Core.
WindowSizeChangedEventArgs e) { windowBounds = Window.Current.Bounds; }
void SettingsOnCommandsRequested(SettingsPane settingsPane,
SettingsPaneCommandsRequestedEventArgs eventArgs) { UICommandInvokedHandler mySettingsHandler
=
new UICommandInvokedHandler(onSettingsCommand); SettingsCommand mySettingsCommand
=
new SettingsCommand("MySettingsId", "My Settings menu",
mySettingsHandler); eventArgs.Request.ApplicationCommands.Add(mySettingsCommand); }

 

Then we also need a handler, which gets executed, when the user clicks the new settings menu. This handler will then create a popup dialog on top of the settings pane, in which the settings flyout page will be added. The folllowing code does exactly this:

 

void onSettingsCommand(IUICommand command)
{
// Create a Popup window which will contain our flyout. settingsPopup = new Popup(); settingsPopup.Closed += OnPopupClosed; Window.Current.Activated += OnWindowActivated; settingsPopup.IsLightDismissEnabled = true; settingsPopup.Width = settingsWidth; settingsPopup.Height = windowBounds.Height; // Add the proper animation for the panel. settingsPopup.ChildTransitions = new TransitionCollection(); settingsPopup.ChildTransitions.Add(new PaneThemeTransition() { Edge = (SettingsPane.Edge == SettingsEdgeLocation.Right) ? EdgeTransitionLocation.Right : EdgeTransitionLocation.Left }); // Create a SettingsFlyout the same dimenssions as the Popup. SettingsFlyout mypane = new SettingsFlyout(); mypane.Width = settingsWidth; mypane.Height = windowBounds.Height; // Place the SettingsFlyout inside our Popup window. settingsPopup.Child = mypane; // Let's define the location of our Popup. settingsPopup.SetValue(Canvas.LeftProperty,
SettingsPane.Edge == SettingsEdgeLocation.Right ?
(windowBounds.Width - settingsWidth) : 0); settingsPopup.SetValue(
Canvas.TopProperty, 0); settingsPopup.IsOpen = true;
}

 
Then we need to make sure, that clicking outside the dialog will automatically close the dialog. This can be done by handling the Activated event and checking for Deactivated state.

Then make sure, that when the dialog really gets dismissed, that the Activated event handler gets removed:

private void OnWindowActivated(object sender, 
                Windows.UI.Core.WindowActivatedEventArgs e)
{
    if (e.WindowActivationState == 
          Windows.UI.Core.CoreWindowActivationState.Deactivated)
    {
        settingsPopup.IsOpen = false;
    }
}


void OnPopupClosed(object sender, object e)
{
    Window.Current.Activated -= OnWindowActivated;
}

..

 

Now clicking on the new menu entry, the system will display the SettingsFlyout.xaml page inside the settings pane.

This page is a regular "Basic page", inheriting from LayoutAwarePage.

Make sure to set the design width attribut to either 346 or 646 so that the designer also displays it in correct way.

The XAML should look like this:

 

<common:LayoutAwarePage
    x:Class="FlyOutSampleApp.Views.SettingsFlyout"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:common="using:FlyOutSampleApp.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="768"
    d:DesignWidth="346">

The the real content of the settingspage must then be added to Row 1 of the LayoutRoot grid:

<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1">

<
Grid Margin="40,33,40,39" VerticalAlignment="Top" Grid.RowSpan="3">
<
StackPanel x:Name="FlyoutContent">
<
TextBlock FontWeight="Bold" Text="My Settings" />
<
ToggleSwitch Name="ts1" Header="WLAN"

OnContent="ON" OffContent="OFF"

Toggled="ts1_Toggled_1" IsOn="True"/>
<!-- ... some more settings controls.. --->

</
StackPanel>
</
Grid>
</
ScrollViewer>

      


The code behind for the SettingsFlyout should have some code for setting the transitions and positions:

public SettingsFlyout()
{
    this.InitializeComponent();
    FlyoutContent.Transitions = new TransitionCollection();
    FlyoutContent.Transitions.Add(new EntranceThemeTransition()
    {
        FromHorizontalOffset = 
        (SettingsPane.Edge == SettingsEdgeLocation.Right) ? 
            ContentAnimationOffset : (ContentAnimationOffset * -1)
    });
}

 

And then finally the back button handling:

private void MySettingsBackClicked(object sender, RoutedEventArgs e)
{
    // First close our Flyout.
    Popup parent = this.Parent as Popup;
    if (parent != null)
    {
        parent.IsOpen = false;
    }

    // If app is not snapped, then back button shows Settings pane again.
    if (Windows.UI.ViewManagement.ApplicationView.Value != 
Windows.UI.ViewManagement.
ApplicationViewState.Snapped) { SettingsPane.Show(); } }
Categories: Metro, Windows 8
  1. October 22, 2012 at 8:11 pm

    Consider using this custom control to makey your life easier:
    http://code.msdn.microsoft.com/windowsapps/CharmFlyout-A-Metro-Flyout-25fe53b6

  1. No trackbacks yet.

Leave a 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 )

Google photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s

%d bloggers like this: