Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

ページを遷移する前に検証する

アプリ実行

名前が入力されたときだけ次のページに受け渡します。

Page1.xaml


Hello.xaml


検証

項目 結果
名前の入力がないとき「続行」をクリックしても遷移しない OK
名前の入力があるとき遷移する OK
遷移すると「戻る」ボタンが有効になる OK
「戻る」ボタンをクリックすると遷移する OK
遷移すると「進む」ボタンが有効になる OK
名前の入力がないとき「続行」をクリックしても遷移しない OK
名前の入力がないとき「進む」ボタンクリックすると遷移する OK

ソースコード

App.xaml
<Application x:Class="Propterty.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="Page1.xaml">
</Application>
Page1.xaml
<Page x:Class="Propterty.Page1"
      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="300" d:DesignWidth="300"
    WindowTitle="あなたは誰?"
    Loaded="Page_Loaded">
    <StackPanel>
        <Label>あなたのお名前は?</Label>
        <TextBox Name="_nameBox"></TextBox>
        <TextBlock>
            <Hyperlink 
                NavigateUri="Hello.xaml"
                Click="Hyperlink_Click">
                続行
            </Hyperlink>
        </TextBlock>
    </StackPanel>
</Page>
Page1.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace Propterty {
    public partial class Page1 : Page {

        /// <summary>
        /// ナビゲーション完了後もアクセスできるようにキャッシュする。
        /// </summary>
        NavigationService _navigation;

        public Page1() {
            InitializeComponent();
        }

        private void Page_Loaded(object sender, RoutedEventArgs e) {
            _navigation = this.NavigationService;
            _navigation.Navigating += new NavigatingCancelEventHandler(_navigation_Navigating);
            _navigation.Navigated += new NavigatedEventHandler(_navigation_Navigated);
        }

        private void Hyperlink_Click(object sender, RoutedEventArgs e) {
            Hello hello = new Hello();
            hello.InputName = _nameBox.Text;
            NavigationService.Navigate(hello);
        }

        /// <summary>
        /// イベントのアンフックと参照のクリアを行う。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _navigation_Navigated(object sender, NavigationEventArgs e) {
            _navigation.Navigating -= _navigation_Navigating;
            _navigation.Navigated -= _navigation_Navigated;
            _navigation = null;
        }

        /// <summary>
        /// 検証
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _navigation_Navigating(object sender, NavigatingCancelEventArgs e) {
            if ((_nameBox.Text.Length == 0) &&
                (e.NavigationMode == NavigationMode.New)) { // 一度訪れたページであれば無条件に遷移できるようにする
                e.Cancel = true;
            }
        }
    }
}
Hello.xaml
<Page x:Class="Propterty.Hello"
      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="300" d:DesignWidth="300"
    WindowTitle="こんにちは">
    <StackPanel>
        <Label Name="_name"></Label>
        <TextBlock>さん、こんにちは!</TextBlock>
    </StackPanel>
</Page>
Hello.xaml.cs
using System.Windows.Controls;

namespace Propterty {
    public partial class Hello : Page {
        public string InputName {
            set { _name.Content = value; }
        }

        public Hello() {
            InitializeComponent();
        }
    }
}

参考

NavigationService.Navigating イベント (System.Windows.Navigation)
新しいナビゲーションが要求されると発生します。 ...

NavigationService.Navigated イベント (System.Windows.Navigation)
移動先のコンテンツが見つかったときに発生します。この時点で Content プロパティからコンテンツを取得できますが、読み込みはまだ完了していない可能性があります。 ...

NavigatingCancelEventArgs クラス (System.Windows.Navigation)
Navigating イベントにデータを提供します。 ...

NavigatingCancelEventArgs.NavigationMode プロパティ (System.Windows.Navigation)
行われているナビゲーションの種類を示す NavigationMode 値を取得します。 ...