質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

1612閲覧

C# WPF NavigationServiceでの画面遷移時に例外が発生する

Hottopia

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2023/03/09 09:22

前提

C# (WPF)に関する質問です。
一定時間操作がない場合に、別の画面に遷移する機能を実装しています。(スクリーンセーバー機能)

1: TimerTestページで無操作の時間が5秒に達すると、ScreenSaverTestページに遷移します。
2: ScreenSaverページ中央のNavigationボタンを押下すると、再度TimerTestページに遷移します。

以上を何回も繰り返して動きを確認する想定でした。

実際にやってみると、1度目の画面遷移は問題ないようですが、2度目の画面遷移からは例外が発生します。
TimerTestページの41行目にブレークポイントを登録してみると、2度目の遷移処理の際、NavigationServiceがnullであることが気になりました。

原因がわからず、知恵をお借りしたいです。

発生している問題・エラーメッセージ

System.NullReferenceException: 'Object reference not set to an instance of an object.' System.Windows.Controls.Page.NavigationService.get が null を返しました。

該当のソースコード

TimerTest.xaml(遷移元)

XAML

1<Page x:Class="Test.TimerTest" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:Test" 7 mc:Ignorable="d" 8 d:DesignHeight="450" d:DesignWidth="800" 9 Title="TimerTest" 10 Loaded="Page_Loaded"> 11 12 <Canvas> 13 <Label Content="TimerTestPage" 14 Height="30" Width="200" 15 Background="White"/> 16 </Canvas> 17</Page>

ScreenSaverTest.xaml.cs

C#

1using System; 2using System.Collections.Generic; 3using System.Diagnostics; 4using System.Text; 5using System.Windows; 6using System.Windows.Controls; 7using System.Windows.Data; 8using System.Windows.Documents; 9using System.Windows.Input; 10using System.Windows.Interop; 11using System.Windows.Media; 12using System.Windows.Media.Imaging; 13using System.Windows.Navigation; 14using System.Windows.Shapes; 15using System.Windows.Threading; 16 17namespace Test 18{ 19 /// <summary> 20 /// TimerTest.xaml の相互作用ロジック 21 /// </summary> 22 public partial class TimerTest : Page 23 { 24 private DispatcherTimer _timer = new DispatcherTimer(); 25 26 public TimerTest() 27 { 28 InitializeComponent(); 29 _timer.Interval = TimeSpan.FromSeconds(5); 30 _timer.Tick += _timer_Tick; 31 _timer.Start(); 32 } 33 private void Page_Loaded(object sender, RoutedEventArgs e) 34 { 35 SetAddHook(); 36 37 } 38 private void _timer_Tick(object sender, EventArgs e) 39 { 40 var screenSaverTest = new ScreenSaverTest(); 41 NavigationService.Navigate(screenSaverTest); 42 } 43 44 45 /// <summary> 46 /// マウスカーソルが移動したことを示すウィンドウメッセージ。 47 /// </summary> 48 private const int WmMouseMove = 0x0200; 49 50 /// <summary> 51 /// マウス左ボタンが押されたことを示す。ウィンドウメッセージ。 52 /// </summary> 53 private const int WmMouseLeftButtonDown = 0x0201; 54 55 private void SetAddHook() 56 { 57 var parenWindow = Window.GetWindow(this); 58 HwndSource source = HwndSource.FromHwnd(new 59 WindowInteropHelper(parenWindow).Handle); 60 source.AddHook(WindowProc); 61 } 62 63 private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 64 { 65 switch (msg) 66 { 67 case WmMouseMove: 68 _timer.Stop(); 69 _timer.Start(); 70 break; 71 72 case WmMouseLeftButtonDown: 73 _timer.Stop(); 74 _timer.Start(); 75 break; 76 77 default: 78 break; 79 } 80 return hwnd; 81 } 82 } 83}

ScreenSaverTest.xaml

XAML

1<Page x:Class="Test.ScreenSaverTest" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:Test" 7 mc:Ignorable="d" 8 d:DesignHeight="450" d:DesignWidth="800" 9 Title="ScreenSaverTest"> 10 11 <Canvas> 12 <Label Content="ScreenSaverTestPage" 13 Height="30" Width="200" 14 Background="White"/> 15 <Button x:Name="Button" 16 Content="NaVigation" 17 Height="50" Width="200" 18 Canvas.Left="300" Canvas.Top="200" 19 Click="Button_Click"/> 20 </Canvas> 21</Page>

ScreenSaverTest.xaml.cs

C#

1using System; 2using System.Collections.Generic; 3using System.Text; 4using System.Windows; 5using System.Windows.Controls; 6using System.Windows.Data; 7using System.Windows.Documents; 8using System.Windows.Input; 9using System.Windows.Media; 10using System.Windows.Media.Imaging; 11using System.Windows.Navigation; 12using System.Windows.Shapes; 13 14namespace Test 15{ 16 /// <summary> 17 /// ScreenSaverTest.xaml の相互作用ロジック 18 /// </summary> 19 public partial class ScreenSaverTest : Page 20 { 21 public ScreenSaverTest() 22 { 23 InitializeComponent(); 24 } 25 26 private void Button_Click(object sender, RoutedEventArgs e) 27 { 28 var timerTestPage = new TimerTest(); 29 NavigationService.Navigate(timerTestPage); 30 } 31 } 32}

補足情報(FW/ツールのバージョンなど)

Visual Studio 2022
C#10.0
WPF

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

TimerTestページの41行目にブレークポイントを登録してみると、2度目の遷移処理の際、> NavigationServiceがnullであることが気になりました。

表示が終わったTimerTestのタイマーが来ているように思います。
Unloadedでタイマーを止めたり、RemoveHookしたほうがいいでしょう。

ナビゲーションは履歴が残ったりライフサイクルが分かりにくかったりで個人的には嫌いですw
ナビゲーションの概要 - WPF .NET Framework | Microsoft Learn(とっくに終わったXBAPの記述があったりと内容が古いですが)


AddHookいります?
親ウィンドウのPreviewMouseLeftButtonDownとかに刺せばいいような?(実はグローバルフックなのかな)

投稿2023/03/09 11:00

TN8001

総合スコア9321

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Hottopia

2023/03/09 11:31 編集

回答ありがとうございます。 Page_Unloadedイベントハンドラでタイマーを停止させ、 タイマーのTickイベントでRemoveHookすることで解決しました。 AddHookいらないですかね? 深く考えずに実装してました。。。 AddHookにすることでデメリットとかありますか?
TN8001

2023/03/09 12:13

> AddHookいらないですかね? まずグローバルフックする(自ウィンドウ外も見たい)ならそうせざるを得ません(あるいはRaw Input) MainWindowがどうなっているかわかりませんが、全体がページならページのイベントでも十分そうですが(Background="Transparent"とか何かしら入れないと来ないです) あとタイトルバーとかだと来ないですね。 > AddHookにすることでデメリットとかありますか? 負荷的な意味ではまあ大差ない気はします。 行数的な意味で(同じことが普通のイベントで済むんなら)無駄かなって思っただけです^^; あと今回のようにライフサイクルが短いもののイベントは削除したりが面倒なので、MainWindow側が管理するほうがあれこれ考えずに済んで楽な気はします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問