Windows 10 Insider Preview 10074 + VS2015 RC時点の情報です
ハンバーガーメニューがぱかぱか開いたりするあの画面です。
ヘッダー部の作成
簡単にヘッダー部分をさくっと作ります。
<Page x:Class="App17.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App17" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <!-- Header --> <RelativePanel> <ToggleButton x:Name="toggleButton" Content="" FontFamily="{ThemeResource SymbolThemeFontFamily}" Background="Transparent" Width="40" Height="40" /> <Button x:Name="buttonBack" Style="{ThemeResource NavigationBackButtonNormalStyle}" RelativePanel.RightOf="toggleButton"/> <TextBlock Text="My App" Style="{ThemeResource TitleTextBlockStyle}" Margin="10, 0" RelativePanel.RightOf="buttonBack" RelativePanel.AlignVerticalCenterWith="buttonBack"/> </RelativePanel> <!-- Body --> <SplitView x:Name="splitView" Grid.Row="1"> </SplitView> </Grid> </Page>
ToggleButtonでハンバーガーメニューのボタンを準備します。文字コードは0xE700なので、それを指定しましょう。ハンバーガーメニューのボタンの横には戻るボタンを用意しておきます。そしてその横には、アプリタイトルを表示しています。
SplitViewの作成
メインのコンテンツ部分はSplitViewで作成しています。これからここを作りこんでいきます。
<!-- Body --> <SplitView x:Name="splitView" Grid.Row="1" IsPaneOpen="{Binding IsChecked, ElementName=toggleButton, Mode=TwoWay}" CompactPaneLength="40"> <SplitView.Pane> <ListView> <ListViewItem> <StackPanel Orientation="Horizontal"> <FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" FontSize="20" /> <TextBlock Text="ItemItemItem" Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0" /> </StackPanel> </ListViewItem> <ListViewItem> <StackPanel Orientation="Horizontal"> <FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" FontSize="20" /> <TextBlock Text="ItemItemItem" Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0" /> </StackPanel> </ListViewItem> <ListViewItem> <StackPanel Orientation="Horizontal"> <FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" FontSize="20" /> <TextBlock Text="ItemItemItem" Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0" /> </StackPanel> </ListViewItem> </ListView> </SplitView.Pane> <Frame x:Name="rootFrame" /> </SplitView>
ListViewに適当なアイテムを3つ置いています。SplitViewは、ここに画面遷移するためのコンテンツを置くためのFrameを置いています。これだけで、大分それっぽくなります。
サイズに応じた見た目の作成
次に、VisualStateを作りこんでいきます。ルートのGridの下に以下のようなVisualStateを定義します。
<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="LayoutVisualStateGroup"> <!-- 最小幅 --> <VisualState x:Name="NarrowLayout"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> </VisualState> <!-- 普通 --> <VisualState x:Name="NormalLayout"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="321" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="splitView.DisplayMode" Value="CompactOverlay" /> </VisualState.Setters> </VisualState> <!-- 広い --> <VisualState x:Name="WideLayout"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="1025" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="splitView.DisplayMode" Value="Inline" /> <Setter Target="toggleButton.IsChecked" Value="True" /> <Setter Target="toggleButton.Visibility" Value="Collapsed" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
こうすると、画面の幅に応じてそれっぽい見た目になってくれます。
電話
パソコンで幅が狭いとき
パソコンで幅が広いとき
RootFrameの差し替え
SplitView内に置いたFrameをアプリケーションのルートのFrameにします。App.xaml.csのOnLaunchedを以下のように書き換えます。(BlankPage1.xamlに初期状態で遷移するようにしています)
/// <summary> /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. /// </summary> /// <param name="e">Details about the launch request and process.</param> protected override void OnLaunched(LaunchActivatedEventArgs e) { #if DEBUG if (System.Diagnostics.Debugger.IsAttached) { this.DebugSettings.EnableFrameRateCounter = true; } #endif var root = Window.Current.Content as MainPage; var rootFrame = root?.FindName("rootFrame") as Frame ?? null; // Do not repeat app initialization when the Window already has content, // just ensure that the window is active if (root == null) { // Create a Frame to act as the navigation context and navigate to the first page root = new MainPage(); rootFrame = root.FindName("rootFrame") as Frame; rootFrame.NavigationFailed += OnNavigationFailed; if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) { //TODO: Load state from previously suspended application } // Place the frame in the current Window Window.Current.Content = root; } if (rootFrame.Content == null) { // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter rootFrame.Navigate(typeof(BlankPage1), e.Arguments); } // Ensure the current window is active Window.Current.Activate(); }
仕上げ
最後にSplitViewのPaneのListViewのListViewItemをクリックしたら画面遷移するようにします。
普通のBehaviorのNavigateToPageActionだと動かないので、自前の画面遷移のアクションを定義します。
using Microsoft.Xaml.Interactivity; using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace App17 { public class CustomNavigateToPageAction : DependencyObject, IAction { public string Page { get { return (string)GetValue(PageProperty); } set { SetValue(PageProperty, value); } } // Using a DependencyProperty as the backing store for Page. This enables animation, styling, binding, etc... public static readonly DependencyProperty PageProperty = DependencyProperty.Register("Page", typeof(string), typeof(CustomNavigateToPageAction), new PropertyMetadata(null)); public object Execute(object sender, object parameter) { var root = Window.Current.Content as MainPage; var frame = root?.FindName("rootFrame") as Frame; frame?.Navigate(Type.GetType(this.Page)); return null; } } }
あとは、ListViewItemをクリックしたときにこのActionが呼ばれるようにすればOK。全体のXAMLは以下のようになります。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App17" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core" x:Class="App17.MainPage" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="LayoutVisualStateGroup"> <!-- 最小幅 --> <VisualState x:Name="NarrowLayout"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> </VisualState> <!-- 普通 --> <VisualState x:Name="NormalLayout"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="321" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="splitView.DisplayMode" Value="CompactOverlay" /> </VisualState.Setters> </VisualState> <!-- 広い --> <VisualState x:Name="WideLayout"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="1025" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="splitView.DisplayMode" Value="Inline" /> <Setter Target="toggleButton.IsChecked" Value="True" /> <Setter Target="toggleButton.Visibility" Value="Collapsed" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <!-- Header --> <RelativePanel> <ToggleButton x:Name="toggleButton" Content="" FontFamily="{ThemeResource SymbolThemeFontFamily}" Background="Transparent" Width="40" Height="40" /> <Button x:Name="buttonBack" Style="{ThemeResource NavigationBackButtonNormalStyle}" RelativePanel.RightOf="toggleButton" /> <TextBlock Text="My App" Style="{ThemeResource TitleTextBlockStyle}" Margin="10, 0" RelativePanel.RightOf="buttonBack" RelativePanel.AlignVerticalCenterWith="buttonBack"/> </RelativePanel> <!-- Body --> <SplitView x:Name="splitView" Grid.Row="1" IsPaneOpen="{Binding IsChecked, ElementName=toggleButton, Mode=TwoWay}" CompactPaneLength="40"> <SplitView.Pane> <ListView> <ListViewItem> <Interactivity:Interaction.Behaviors> <Core:EventTriggerBehavior EventName="Tapped"> <local:CustomNavigateToPageAction Page="App17.BlankPage1"/> </Core:EventTriggerBehavior> </Interactivity:Interaction.Behaviors> <StackPanel Orientation="Horizontal"> <FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" FontSize="20" /> <TextBlock Text="ItemItemItem" Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0" /> </StackPanel> </ListViewItem> <ListViewItem> <Interactivity:Interaction.Behaviors> <Core:EventTriggerBehavior EventName="Tapped"> <local:CustomNavigateToPageAction Page="App17.BlankPage2"/> </Core:EventTriggerBehavior> </Interactivity:Interaction.Behaviors> <StackPanel Orientation="Horizontal"> <FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" FontSize="20" /> <TextBlock Text="ItemItemItem" Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0" /> </StackPanel> </ListViewItem> <ListViewItem> <StackPanel Orientation="Horizontal"> <Interactivity:Interaction.Behaviors> <Core:EventTriggerBehavior EventName="Tapped"> <local:CustomNavigateToPageAction Page="App17.BlankPage3"/> </Core:EventTriggerBehavior> </Interactivity:Interaction.Behaviors> <FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" FontSize="20" /> <TextBlock Text="ItemItemItem" Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0" /> </StackPanel> </ListViewItem> </ListView> </SplitView.Pane> <Frame x:Name="rootFrame" /> </SplitView> </Grid> </Page>