atelier:mitsuba

i love UI/UX, Blend, XAML, Behavior, P5, oF, Web, Tangible Bits and Physical computing. なにかあればお気軽にご連絡ください。atelier@c-mitsuba.com

その14:Frame in FrameでPopup風デザインを実装する

Windows 8 Developer Previewなので正式版とは異なる場合があります。
また、Windows Updateが走るときもあるため、エントリ執筆現在の情報をもとにかいています。


その13で紹介したMessageDialogは文字列を表示するためのものでした。
今回はFrame in Frameを使って、PopupなWindowを実装します。

とりあえずこんなかんじ。
ボタンを押すとー

FrameにホストされたPageが表示されます。

まず、MainPage.xaml
Frameコントロールだけ設置したUserControlです。
デフォルトでMainFrame.xamlがホストされてます。

<UserControl x:Class="Application19.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    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="1366">
   
    <Grid x:Name="LayoutRoot" Background="Black">
        <Frame x:Name="Frame" Source="Application19.MainFrame"></Frame>
    </Grid>
   
</UserControl>

で、これがMainFrame.xaml。緑色の画面ですね。
Frameを非表示で設置しています。

<Page x:Class="Application19.MainFrame"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Loaded="Page_Loaded" Unloaded="Page_Unloaded"
    mc:Ignorable="d"
    d:DesignWidth="1366" d:DesignHeight="768">

    <!--Common resources for default dark theme applications-->
    <UserControl.Resources>
        <SolidColorBrush x:Key="PageBackgroundBrush" Color="#FF1A1A1A"/>
        <SolidColorBrush x:Key="PageForegroundBrush" Color="White"/>
        <SolidColorBrush x:Key="HighlightBrush" Color="#FF26A0DA"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="Green">
        <Button Content="Show Popup Frame" HorizontalAlignment="Center" FontSize="80" Click="Button_Click"></Button>
        <Frame x:Name="Frame" Visibility="Collapsed"></Frame>
    </Grid>
</Page>


ボタンがクリックされると、Page内にあるFrameにPopupFrame.xamlを表示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;


namespace Application19
{
    public sealed partial class MainFrame
    {
        public MainFrame()
        {
            InitializeComponent();
        }


        // View state management for switching among Full, Fill, Snapped, and Portrait states


        private DisplayPropertiesEventHandler _displayHandler;
        private TypedEventHandler<ApplicationLayout, ApplicationLayoutChangedEventArgs> _layoutHandler;


        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            if (_displayHandler == null)
            {
                _displayHandler = Page_OrientationChanged;
                _layoutHandler = Page_LayoutChanged;
            }
            DisplayProperties.OrientationChanged += _displayHandler;
            ApplicationLayout.GetForCurrentView().LayoutChanged += _layoutHandler;
            SetCurrentOrientation(this);
        }


        private void Page_Unloaded(object sender, RoutedEventArgs e)
        {
            DisplayProperties.OrientationChanged -= _displayHandler;
            ApplicationLayout.GetForCurrentView().LayoutChanged -= _layoutHandler;
        }


        private void Page_LayoutChanged(object sender, ApplicationLayoutChangedEventArgs e)
        {
            SetCurrentOrientation(this);
        }


        private void Page_OrientationChanged(object sender)
        {
            SetCurrentOrientation(this);
        }


        private void SetCurrentOrientation(Control viewStateAwareControl)
        {
            VisualStateManager.GoToState(viewStateAwareControl, this.GetViewState(), false);
        }


        private String GetViewState()
        {
            var orientation = DisplayProperties.CurrentOrientation;
            if (orientation == DisplayOrientations.Portrait ||
                orientation == DisplayOrientations.PortraitFlipped) return "Portrait";
            var layout = ApplicationLayout.Value;
            if (layout == ApplicationLayoutState.Filled) return "Fill";
            if (layout == ApplicationLayoutState.Snapped) return "Snapped";
            return "Full";
        }


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Frame.Visibility = Visibility.Visible;
            Frame.Navigate("Application19.PopupFrame");
        }
    }
}

最後に、PopupPage.xamlです。 
一番大きいGridを半透明にし、中にコンテンツを表示する小さいGridを設置します。
小さいGridの方に、表示したい内容を書きます。

<Page x:Class="Application19.PopupFrame"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Loaded="Page_Loaded" Unloaded="Page_Unloaded"
    mc:Ignorable="d"
    d:DesignWidth="1366" d:DesignHeight="768">

    <!--Common resources for default dark theme applications-->
    <UserControl.Resources>
        <SolidColorBrush x:Key="PageBackgroundBrush" Color="#FF1A1A1A"/>
        <SolidColorBrush x:Key="PageForegroundBrush" Color="White"/>
        <SolidColorBrush x:Key="HighlightBrush" Color="#FF26A0DA"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="#991A1A1A">
        <Grid Width="680" Height="420" Background="#FF1A00BB">
            <Button Content="Close Popup" Click="Button_Click" HorizontalAlignment="Center"></Button>
        </Grid>
    </Grid>
</Page>


ボタンがクリックされると、自身のFrameを非表示にします。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace Application19
{
    public sealed partial class PopupFrame
    {
        public PopupFrame()
        {
            InitializeComponent();
        }

        // View state management for switching among Full, Fill, Snapped, and Portrait states

        private DisplayPropertiesEventHandler _displayHandler;
        private TypedEventHandler<ApplicationLayout, ApplicationLayoutChangedEventArgs> _layoutHandler;

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            if (_displayHandler == null)
            {
                _displayHandler = Page_OrientationChanged;
                _layoutHandler = Page_LayoutChanged;
            }
            DisplayProperties.OrientationChanged += _displayHandler;
            ApplicationLayout.GetForCurrentView().LayoutChanged += _layoutHandler;
            SetCurrentOrientation(this);
        }

        private void Page_Unloaded(object sender, RoutedEventArgs e)
        {
            DisplayProperties.OrientationChanged -= _displayHandler;
            ApplicationLayout.GetForCurrentView().LayoutChanged -= _layoutHandler;
        }

        private void Page_LayoutChanged(object sender, ApplicationLayoutChangedEventArgs e)
        {
            SetCurrentOrientation(this);
        }

        private void Page_OrientationChanged(object sender)
        {
            SetCurrentOrientation(this);
        }

        private void SetCurrentOrientation(Control viewStateAwareControl)
        {
            VisualStateManager.GoToState(viewStateAwareControl, this.GetViewState(), false);
        }

        private String GetViewState()
        {
            var orientation = DisplayProperties.CurrentOrientation;
            if (orientation == DisplayOrientations.Portrait ||
                orientation == DisplayOrientations.PortraitFlipped) return "Portrait";
            var layout = ApplicationLayout.Value;
            if (layout == ApplicationLayoutState.Filled) return "Fill";
            if (layout == ApplicationLayoutState.Snapped) return "Snapped";
            return "Full";
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Frame.Visibility = Visibility.Collapsed;
        }
    }
}


これでPopupなデザインが実現できました。
簡単ですね。