Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

Universal Windows Platform appっぽいSplitViewを使った画面の作り方

$
0
0
Windows 10 Insider Preview 10074 + VS2015 RC時点の情報です

ハンバーガーメニューがぱかぱか開いたりするあの画面です。

ヘッダー部の作成

簡単にヘッダー部分をさくっと作ります。

<Pagex: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="&#xE700;"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="&#xE701;"FontSize="20" /><TextBlock Text="ItemItemItem"Style="{ThemeResource BodyTextBlockStyle}"Margin="10,0" /></StackPanel></ListViewItem><ListViewItem><StackPanel Orientation="Horizontal"><FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"Glyph="&#xE702;"FontSize="20" /><TextBlock Text="ItemItemItem"Style="{ThemeResource BodyTextBlockStyle}"Margin="10,0" /></StackPanel></ListViewItem><ListViewItem><StackPanel Orientation="Horizontal"><FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"Glyph="&#xE703;"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を置いています。これだけで、大分それっぽくなります。

f:id:okazuki:20150506152337p:plain

サイズに応じた見た目の作成

次に、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>

こうすると、画面の幅に応じてそれっぽい見た目になってくれます。

電話

f:id:okazuki:20150506153604p:plainf:id:okazuki:20150506153631p:plain

パソコンで幅が狭いとき

f:id:okazuki:20150506153747p:plainf:id:okazuki:20150506153802p:plain

パソコンで幅が広いとき

f:id:okazuki:20150506153857p:plain

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>/// <paramname="e">Details about the launch request and process.</param>protectedoverridevoid OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUGif (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 activeif (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
{
    publicclass CustomNavigateToPageAction : DependencyObject, IAction
    {
        publicstring 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...publicstaticreadonly DependencyProperty PageProperty =
            DependencyProperty.Register("Page", typeof(string), typeof(CustomNavigateToPageAction), new PropertyMetadata(null));

        publicobject 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));
            returnnull;
        }
    }
}

あとは、ListViewItemをクリックしたときにこのActionが呼ばれるようにすればOK。全体のXAMLは以下のようになります。

<Pagexmlns="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="&#xE700;"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="&#xE701;"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="&#xE702;"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="&#xE703;"FontSize="20" /><TextBlock Text="ItemItemItem"Style="{ThemeResource BodyTextBlockStyle}"Margin="10,0" /></StackPanel></ListViewItem></ListView></SplitView.Pane><Frame x:Name="rootFrame" /></SplitView></Grid></Page>

Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>