はじめに
前回からだいぶ間が空いてしまいましたが、
今回は、

また、
設定ウィンドウと設定ポップアップ
Windowsストア アプリでは、
設定ウィンドウ
図1はSkyDriveの設定ウィンドウです。
ウィンドウ上部にアプリの設定項目が表示されています。Windowsストアからインストールしたアプリは、
ユーザーが設定ウィンドウを開いた時、
設定ウィンドウ下部は、
設定ポップアップ
設定ウィンドウに表示されるアプリの設定項目は、
SkyDriveの

設定ウィンドウや設定ポップアップに、
設定ウィンドウが重要な理由
冒頭で触れた設定ウィンドウがアプリ認定に重要な理由ですが、
このため、
ちなみに、
設定ウィンドウにアプリ設定項目の追加
それでは実際にコーディングしていきましょう。
プロジェクトの作成
Visual Studioでプロジェクトを作成します。今回も前回と同じく、

アプリの設定項目の追加
さっそく、
設定ウィンドウのオブジェクト
// using Windows.UI.ApplicationSettings; の追加が必要です
bool EventRegistered;
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.EventRegistered)
{
SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;
this.EventRegistered = true;
}
// (省略)
}
OnCommandsRequestedの内容は次のようになります。ここで実際に項目を設定ウィンドウに追加しています。項目となるSettingsCommandオブジェクトを生成してApplicationCommands配列に追加します。
ここでSettingsCommandオブジェクト生成時に指定している値は、
// using Windows.UI.Popups; の追加が必要です
void OnCommandsRequested(SettingsPane settingsPane, SettingsPaneCommandsRequestedEventArgs eventArgs)
{
var handler = new UICommandInvokedHandler(OnSettingsCommand);
var policyCommand = new SettingsCommand("policy", "プライバシーポリシー", handler);
eventArgs.Request.ApplicationCommands.Add(policyCommand);
}
続いて、
ここではWebページを表示するようにしています。
void OnSettingsCommand(IUICommand command)
{
var settingsCommand = (SettingsCommand)command;
switch (settingsCommand.Id.ToString())
{
case "policy":
ShowPrivacyPolicy();
break;
}
}
// プライバシーポリシーの表示
// using Windows.System; の追加が必要です
async void ShowPrivacyPolicy()
{
Uri uri = new Uri("http://example.jp/privacypolicy");
await Launcher.LaunchUriAsync(uri);
}
ここまでを実行してみましょう。設定チャームから設定ウィンドウを開くと追加した項目が表示されたでしょうか

以上で、
設定ポップアップの表示
続いて、
メニューの

XAMLの内容を変更します。ひとまず動作がわかるよう文字を表示するだけの簡単な内容にしておきます。
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<TextBlock>サンプル</TextBlock>
</Grid>
項目の追加
設定ポップを表示するための項目を設定ウィンドウに追加しましょう。OnCommandsRequestedメソッドにコードを追記します
void OnCommandsRequested(SettingsPane settingsPane, SettingsPaneCommandsRequestedEventArgs eventArgs)
{
var handler = new UICommandInvokedHandler(OnSettingsCommand);
var accountCommand = new SettingsCommand("account", "アカウント", handler);
eventArgs.Request.ApplicationCommands.Add(accountCommand);
var policyCommand = new SettingsCommand("policy", "プライバシーポリシー", handler);
eventArgs.Request.ApplicationCommands.Add(policyCommand);
}
OnSettingsCommandメソッドは、
void OnSettingsCommand(IUICommand command)
{
var settingsCommand = (SettingsCommand)command;
switch (settingsCommand.Id.ToString())
{
case "policy":
ShowHelp();
break;
case "account":
ShowSettingsFlyout();
break;
}
}
設定ポップアップ処理
ShowSettingsFlyoutメソッドに設定ポップアップを表示するコードを記述します。
手順は、
private Popup popup;
void ShowSettingsFlyout()
{
var bounds = Window.Current.Bounds;
var width = 646; // 横幅は UI ガイドラインによると 346 または 646
// Popupオブジェクトの生成
popup = new Popup();
popup.IsLightDismissEnabled = true;
popup.Width = width;
popup.Height = bounds.Height;
// アニメーション設定
popup.ChildTransitions = new Windows.UI.Xaml.Media.Animation.TransitionCollection();
popup.ChildTransitions.Add(new Windows.UI.Xaml.Media.Animation.PaneThemeTransition()
{
Edge = (SettingsPane.Edge == SettingsEdgeLocation.Right) ?
EdgeTransitionLocation.Right :
EdgeTransitionLocation.Left
});
// SettingsFlyout オブジェクトを生成し、Popup.Child プロパティに指定
var pane = new SettingsFlyout();
pane.Width = width;
pane.Height = bounds.Height;
popup.Child = pane;
// ポップアップの位置を調整し、表示
popup.SetValue(Canvas.LeftProperty, SettingsPane.Edge == SettingsEdgeLocation.Right ? (bounds.Width - width) : 0);
popup.SetValue(Canvas.TopProperty, 0);
popup.IsOpen = true;
}
以上で、
アカウント設定ポップアップの作成
さて、

例としてMicrosoftアカウントへサインイン・
サインインUXのガイドライン
ここでサインインに関するガイドラインを確認しましょう。
SkyDriveなどMicrosoftアカウントを使ってデータにアクセスするWindowsストア アプリは、
サインインするタイミングは、
サインインしなくても使えるアプリの場合は、
詳しくは、
設定ポップアップのデザインと動作
それでは、
見た目の部分は、
<UserControl.Resources>
<Style x:Key="SettingsBackButtonStyle" TargetType="Button">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="FontFamily" Value="Segoe UI Symbol"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="26.66667"/>
<Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
<Setter Property="AutomationProperties.Name" Value="Back"/>
<Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid" Width="30" Height="30">
<Grid Margin="-6,-6,0,0">
<TextBlock x:Name="BackgroundGlyph" Text="" Foreground="Transparent"/>
<TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="White"/>
<TextBlock x:Name="ArrowGlyph" Text="" Foreground="#00b2f0" Opacity="0"/>
</Grid>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"
/>
<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"
/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="ArrowGlyph"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="NormalGlyph"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Border BorderBrush="#00b2f0" BorderThickness="1,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="#00b2f0" Grid.Row="0">
<StackPanel Orientation="Horizontal" Margin="40 32 17 13">
<Button Click="BackButton_Click" Style="{StaticResource SettingsBackButtonStyle}"/>
<TextBlock Margin="7 2 0 0" FontSize="26" Text="アカウント" Foreground="White" />
</StackPanel>
</Grid>
<Grid Margin="40,33,40,39" VerticalAlignment="Top" Grid.Row="1">
<StackPanel x:Name="FlyoutContent">
<TextBlock x:Name="MessageTextBlock" Margin="0 24 0 0" Text="サインインしていません" TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" />
<Button x:Name="SignInButton" Margin="0 24 0 0" Content="サインイン" Click="SignInButton_Click" IsEnabled="False" />
<Button x:Name="SignOutButton" Margin="0 24 0 0" Content="サインアウト" Click="SignOutButton_Click" Visibility="Collapsed" />
</StackPanel>
</Grid>
</Grid>
</Border>
次にプロジェクトのデフォルトでは、
<Application
x:Class="GihyoSampleApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
RequestedTheme="Light">
加えて、
<ToolTipService.Placement>マウス</ToolTipService.Placement>
次に、
// using Windows.UI.ApplicationSettings; の追加が必要です
private void BackButton_Click(object sender, RoutedEventArgs e)
{
// ポップアップの非表示
Popup parent = this.Parent as Popup;
if (parent != null)
{
parent.IsOpen = false;
}
// アプリがスナップされていない場合にのみ設定ウィンドウを表示
if (Windows.UI.ViewManagement.ApplicationView.Value != Windows.UI.ViewManagement.ApplicationViewState.Snapped)
{
SettingsPane.Show();
}
}
以上で、
サインイン・サインアウト処理
最後にサインイン・
まず、
static public LiveAuthClient AuthClient;
設定ポップアップのコードは次のように編集します。サインインとサインアウト機能を実装し、
// using Microsoft.Live; の追加が必要です
// コンストラクタを以下のように修正します
public SettingsFlyout()
{
this.InitializeComponent();
// 初期表示
if (App.AuthClient == null || App.AuthClient.Session == null)
{
ShowSignedOutUI();
}
else
{
// ポップアップ表示時にサインインしている可能性がある場合、情報の取得を試行して表示を変更する
ShowSignedInUI();
}
}
// サインインボタン クリック時
private async void SignInButton_Click(object sender, RoutedEventArgs e)
{
if (App.AuthClient == null)
{
// LiveAuthClient オブジェクトが生成されていない場合
App.AuthClient = new LiveAuthClient();
}
this.SignInButton.IsEnabled = false;
try
{
// サインイン
var authResult = await App.AuthClient.LoginAsync(new string[] { "wl.basic" });
if (authResult.Status == LiveConnectSessionStatus.Connected)
{
ShowSignedInUI();
}
else
{
this.SignInButton.IsEnabled = true;
}
}
catch (LiveConnectException)
{
ShowSignedOutUI();
}
}
// サインアウトボタン クリック時
private void SignOutButton_Click(object sender, RoutedEventArgs e)
{
if (App.AuthClient != null)
{
if (!App.AuthClient.CanLogout)
{
return;
}
App.AuthClient.Logout();
App.AuthClient = null;
}
ShowSignedOutUI();
}
// サインアウトしている状態の時の UI 表示
private void ShowSignedOutUI()
{
this.MessageTextBlock.Text = "サインインしていません";
this.SignOutButton.Visibility = Visibility.Collapsed;
this.SignInButton.Visibility = Visibility.Visible;
this.SignInButton.IsEnabled = true;
}
// サインインしている状態の時の UI 表示
private async void ShowSignedInUI()
{
try
{
var connectClient = new LiveConnectClient(App.AuthClient.Session);
// サインインしているユーザー名の取得
LiveOperationResult opMeResult = await connectClient.GetAsync("me");
dynamic meResult = opMeResult.Result;
this.MessageTextBlock.Text = "こんにちは! " + meResult.name;
this.SignInButton.Visibility = Visibility.Collapsed;
// サインアウト可能な場合にのみサインアウトボタン表示
if (App.AuthClient.CanLogout)
{
this.SignOutButton.Visibility = Visibility.Visible;
this.SignOutButton.IsEnabled = true;
}
else
{
this.SignOutButton.Visibility = Visibility.Collapsed;
}
}
catch (LiveConnectException)
{
ShowSignedOutUI();
}
}
WindowsにMicrosoftアカウントでサインインしている場合、
おわりに
今回はここまでです。いかがでしたか。Windowsストア アプリで設定チャームと連携方法を紹介しました。
Visual Studioのプロジェクトテンプレートから作成したアプリには設定チャームの実装があらかじめ記述されていませんが、
日本マイクロソフトが提供している
また、
次回もまたWindowsストア アプリの開発について紹介する予定です。