2013年10月14日

WPFサンプル:NavigationServiceを使ったページ遷移

   このエントリーをはてなブックマークに追加 Clip to Evernote
ウィザード画面のように、次へ、前へボタンがあるようなプログラムを WPFのナビゲーション機能を使って実装したサンプルを掲載します。

どんなプログラムなのかイメージがわくように、まずは実行時のスクリーンショットをお見せします。

Navi1

Navi2

Navi3

以下、作成手順です。

1. ウィンドウの作成 WPFアプリケーションプロジェクトを新規作成してできる MainWindowのXAMLを以下のように変更します。

<Window x:Class="PageNavigationSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="325">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="32"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Background="#FF043957">
            <TextBlock Margin="10,0,0,0" VerticalAlignment="Center" Text="ページ遷移サンプル"
                       Foreground="White"/>
        </StackPanel>
        <Frame Grid.Row="1" NavigationUIVisibility="Hidden" Name="myFrame" />
        <StackPanel Orientation="Horizontal" Background="#FF043957" Grid.Row="2">
            <Button Name="prevButton" Content="Prev" HorizontalAlignment="Left"
                    Margin="10,0,0,0" Grid.Row="2" VerticalAlignment="Center"
                    Width="50" />
            <Button Name="nextButton" Content="Next" HorizontalAlignment="Left"
                    VerticalAlignment="Center" Width="50"  />
        </StackPanel>
    </Grid>
</Window>

■ デザイン時のスクリーンショット
Navi4

Gridを3つに分割し、真ん中にFrameを配置しています、ここに次の「ページの作成」で作成するページが表示されることになります。
下の段には、Prev, Nextボタンを配置します。


2. 各ページの作成 ソリューションエクスプローラでプロジェクトを右クリックし、[追加(D)]-[ページ(P)]で3つのページをプロジェクトに追加してください。[ウィンドウの追加]ではありませんので注意してください。それぞれのページを以下のようにデザインします。

Navi5

3つのページ共に、TextBlockを貼り付けただけの簡単なものです。

#ページ1
<Page x:Class="PageNavigationSample.Step01Page"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      d:DesignHeight="186" d:DesignWidth="325"     Title="Step01Page1">
    <Grid>
        <TextBlock HorizontalAlignment="Left" Margin="20,20,0,0" TextWrapping="Wrap"
                   Text="ページ 1 " VerticalAlignment="Top"/>
    </Grid>
</Page>

#ページ2
<Page x:Class="PageNavigationSample.Step02Page"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      d:DesignHeight="186" d:DesignWidth="300"
     Title="Step02Page1">
    <Grid>
        <TextBlock HorizontalAlignment="Left" Margin="40,30,0,0" TextWrapping="Wrap"
                   Text="ページ 2 " VerticalAlignment="Top"/>
    </Grid>
</Page>

#ページ3
<Page x:Class="PageNavigationSample.Step03Page"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      d:DesignHeight="186" d:DesignWidth="300"
     Title="Step03Page1">
    <Grid>
        <TextBlock HorizontalAlignment="Left" Margin="60,40,0,0" TextWrapping="Wrap"
                   Text="ページ 3 " VerticalAlignment="Top"/>
    </Grid>
</Page>

3. NavigationServiceオブジェクトをフィールドに定義します。
public MainWindow() {
    InitializeComponent();
    _navi = this.myFrame.NavigationService;
}
private NavigationService _navi; 

NavigationServiceクラスは、戻る、進むなどのページナビゲーションを管理するためのクラスです。Frameは、ナビゲーションをサポートするコンテンツコントロールであり、 NavigationServiceプロパティがあります。
NavigationServiceオブジェクトを参照するのに、そのつど、Drameオブジェクトから取得するのは面倒なので、MainWindowのコンストラクタで、_navi フィールドに値をセットしています。

4. 初期ページを指定する
いろいろな方法が考えられますが、ここではもっとも手軽と思われる、コードビハインド側で指定することとします。Frameの Loadedイベントハンドラを以下のように記述します。
private List<Uri> _uriList = new List<Uri>() {
    new Uri("Step01Page.xaml",UriKind.Relative),
    new Uri("Step02Page.xaml",UriKind.Relative),
    new Uri("Step03Page.xaml",UriKind.Relative),
};
private void myFrame_Loaded(object sender, RoutedEventArgs e) {
    _navi.Navigate(_uriList[0]);
}

今回は、3つのページを管理するので、3ページのUriをListに記憶してお、その先頭のページを、NavigateメソッドでFrameに表示しています。

5. Prev, Next ボタンクリック時の動作を実装する
ボタンクリックのイベントハンドラを以下のように記述します。

private void prevButton_Click(object sender, RoutedEventArgs e) {
    if (_navi.CanGoBack)
        _navi.GoBack();
    else {
        int index = _uriList.FindIndex(p => p == _navi.CurrentSource) - 1;
        _navi.Navigate(_uriList[index]);
    }
}
private void nextButton_Click(object sender, RoutedEventArgs e) {
    if (_navi.CanGoForward)
        _navi.GoForward();
    else {
        int index = _uriList.FindIndex(p => p == _navi.CurrentSource) + 1;
        _navi.Navigate(_uriList[index]);
    }
}

一度訪れたページは、GoBack, GoForwordでページ遷移ができますので、Navigateメソッドではなく、GoBack, GoForword メソッドを使います。
まだ訪れていないページの場合は、Navigateメソッドでページ遷移をします。

6. ボタンのIsEnableを制御する

先頭ページの時は、Prevボタンを非活性化させボタンを押せないようにする必要があります。最後のページも同様ですね。
ここでは、FrameのNavigatedイベントで実装することとします。

private void myFrame_Navigated(object sender, NavigationEventArgs e) {
    int index = _uriList.IndexOf(_navi.CurrentSource);
    if (index <= 0)
        prevButton.IsEnabled = false;
    else
        prevButton.IsEnabled = true;
    if (index + 1 == _uriList.Count)
        nextButton.IsEnabled = false;
    else
        nextButton.IsEnabled = true;
}

以上で実装が完了です。


最後に、イベントハンドラの設定を追加したMainWindowのXAMLを掲載します。

<Window x:Class="PageNavigationSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="325">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="32"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Background="#FF043957">
            <TextBlock Margin="10,0,0,0" VerticalAlignment="Center" Text="ページ遷移サンプル"
                       Foreground="White"/>
        </StackPanel>
        <Frame Grid.Row="1" NavigationUIVisibility="Hidden" Name="myFrame"
               Loaded="myFrame_Loaded" Navigated="myFrame_Navigated" />
        <StackPanel Orientation="Horizontal" Background="#FF043957" Grid.Row="2">
            <Button Name="prevButton" Content="Prev" HorizontalAlignment="Left"
                    Margin="10,0,0,0" Grid.Row="2" VerticalAlignment="Center"
                    Width="50" Click="prevButton_Click"/>
            <Button Name="nextButton" Content="Next" HorizontalAlignment="Left"
                    VerticalAlignment="Center" Width="50" Click="nextButton_Click" />
        </StackPanel>
    </Grid>
</Window>



WPFサンプル・目次


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52335648