読者です 読者をやめる 読者になる 読者になる

SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

NavigationWindowを使った時の、F5キーやBackSpaceなどのNavigationCommandsを無効にする

C# WPF


以前↓に書いたNavigationWindowですが、
http://d.hatena.ne.jp/minami_SC/20130831/1377942291
このWindowでは、F5キーでページの再読み込みをしたり、Backspaceで前のページに戻るなどのショートカットキーが効きます。

サンプルコード

まずは、NavigationCommandが有効になった状態の、通常のサンプル。
コードビハインドは、Page2のボタン押下イベントだけ書いています。

これを実行して、F5キーや、BackSpace、マウスなどについてる戻るボタンとかを押すと、ページを戻る動作や再読み込みなどが行われてしまいます。

MainWindow.xaml
<NavigationWindow x:Class="WpfApplication1.MainWindow"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  Title="MainWindow"
                  Width="525"
                  Height="350"
                  Source="Page1.xaml">
</NavigationWindow>
Page1.xaml
<Page x:Class="WpfApplication1.Page1"
      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"
      Title="Page1"
      d:DesignHeight="300"
      d:DesignWidth="300"
      mc:Ignorable="d">
    <StackPanel>
        <TextBlock Margin="10"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   Text="Page1"
                   TextWrapping="Wrap" />
        <TextBlock Margin="10"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   TextWrapping="Wrap">
            <Run Text="リンク:" />
            <Hyperlink NavigateUri="Page2.xaml">
                <Run Text="Page2へ遷移します" />
            </Hyperlink>
        </TextBlock>
        <TextBox Width="120"
                 Height="23"
                 Margin="10"
                 HorizontalAlignment="Left"
                 VerticalAlignment="Top"
                 Text="TextBox"
                 TextWrapping="Wrap" />
    </StackPanel>
</Page>
Page2.xaml
<Page x:Class="WpfApplication1.Page2"
      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"
      Title="Page2"
      d:DesignHeight="300"
      d:DesignWidth="300"
      mc:Ignorable="d">
    <StackPanel>
        <TextBlock Margin="10"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   Text="Page2"
                   TextWrapping="Wrap" />
        <Button Width="75"
                Margin="10"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                Click="Button_Click"
                Content="Button" />
    </StackPanel>
</Page>
Page2.xaml.cs
    public partial class Page2 : Page
    {
        public Page2()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var nav = this.NavigationService;
            nav.GoBack();
        }
    }

対処方法

てことで、NavigationCommandsを無効にする方法を調べました。
※参考サイト
http://social.msdn.microsoft.com/Forums/vstudio/en-US/e280daf1-1ee5-4b10-83cb-57ec70ce266f/disable-navigation-hotkeys-in-a-wpf-navigation-app?forum=wpf


どうやら、NavigationWindowのコンストラクタで、これらのコマンドに対して何も行わないメソッドをCommandBindingしておけば良いっぽい。
こうすると、Navigation系のコマンドでの操作は無効になるけど、NavigationService.GoBackとかのメソッドでの遷移は通常通りできるようになります。

MainWindow.xaml.cs
        public MainWindow()
        {
            InitializeComponent();

            this.CommandBindings.Add(new CommandBinding(NavigationCommands.Refresh, DoNothing));
            this.CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseBack, DoNothing));
            this.CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseForward, DoNothing));
        }

        private void DoNothing(object sender, ExecutedRoutedEventArgs e)
        {
        }


ただし、BrowseBackなどのコマンド自体は実行可能な状態になっているため、↓のようにNavigationWindowの戻る/進むボタンが有効になってしまっています。(このボタンを押しても戻る/進む動作はしなくなってますが、、)

わざわざNavigation系のショートカットを無効にするような場合は、ShowsNavigationUIプロパティもFalseにしてこの辺のボタンも見えなくするだろうから、とりあえずこんな対処でいいかな。。

その他

空のメソッドにバインドするってのは、なんか気持ち悪かったので、
登録してあるNavigationCommandをクリアできないか、以下のようなコードをコンストラクタで書いてみました。

            NavigationCommands.Refresh.InputGestures.Clear();
            NavigationCommands.BrowseBack.InputGestures.Clear();
            NavigationCommands.BrowseForward.InputGestures.Clear();

で、結果ですが、
InputGesturesをクリアした時は、キーボードのショートカット(F5とかBackspace)は無効にできたのですが、
マウスについてる戻るボタンなどの動作を無効にできませんでした。
なんか、この辺をスッキリ実装する方法ないかなぁ。。。