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

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

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

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

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

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

Q&A

解決済

1回答

5604閲覧

[WPF][MVVM]画面遷移時のパラメータ取得方法について

WTB_21

総合スコア12

C#

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

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

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

1グッド

1クリップ

投稿2020/06/30 05:26

編集2020/06/30 05:53

画面遷移先でパラメータの受け方がわからない

MVVMパターンでの画面遷移を実装したいと考えています。
参考ページを参考にして画面遷移自体は出来たのですが、遷移先でパラメータの取得方法がわからずに悩んでいます。

作成したコード

メインウインドウ

XAML

1<NavigationWindow x:Class="NavigationTest.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:NavigationTest" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9</NavigationWindow>

C#

1 public partial class MainWindow : NavigationWindow 2 { 3 public MainWindow() 4 { 5 InitializeComponent(); 6 var NextPage = new Page1View(); 7 NavigationService.Navigate(NextPage); 8 9 } 10 }

ページ1

XAML

1<Page x:Class="NavigationTest.Page1View" 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 mc:Ignorable="d" 7 d:DesignHeight="450" d:DesignWidth="800" 8 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 9 xmlns:b="clr-namespace:Common" 10 xmlns:vm="clr-namespace:NavigationTest" 11 Title="Page1"> 12 <Page.DataContext> 13 <vm:Page1ViewModel x:Name="Page1ViewModel"/> 14 </Page.DataContext> 15 <Grid> 16 <Button Content="Page2へ" > 17 <i:Interaction.Behaviors> 18 <b:NavigateButtonBehaivior NavigatePage="Page2View.xaml" NavigateExtraData="TEST" /> 19 </i:Interaction.Behaviors> 20 </Button> 21 </Grid> 22</Page>

ページ2

XAML

1<Page x:Class="NavigationTest.Page2View" 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 mc:Ignorable="d" 7 d:DesignHeight="450" d:DesignWidth="800" 8 xmlns:vm="clr-namespace:NavigationTest" 9 Title="Page2"> 10 <Page.DataContext> 11 <vm:Page2ViewModel x:Name="Page2ViewModel"/> 12 </Page.DataContext> 13 <Grid> 14 <Label Content="{Binding LabelContent}"/> 15 </Grid> 16</Page>

ビヘイビアクラス

C#

1 public class NavigateButtonBehaivior : Behavior<ButtonBase> 2 { 3 public static readonly DependencyProperty NavigatePageProperty = 4 DependencyProperty.Register("NavigatePage", typeof(Uri), typeof(NavigateButtonBehaivior), new UIPropertyMetadata(null)); 5 6 public static readonly DependencyProperty NavigateExtraDataProperty = 7 DependencyProperty.Register("NavigateExtraData", typeof(object), typeof(NavigateButtonBehaivior), new UIPropertyMetadata(null)); 8 9 /// <summary> 10 /// 遷移先のページ 11 /// </summary> 12 public Uri NavigatePage 13 { 14 get { return (Uri)GetValue(NavigatePageProperty); } 15 16 set { SetValue(NavigatePageProperty, value); } 17 } 18 19 /// <summary> 20 /// 遷移先に渡すパラメータ 21 /// </summary> 22 public object NavigateExtraData 23 { 24 get { return GetValue(NavigateExtraDataProperty); } 25 26 set { SetValue(NavigateExtraDataProperty, value); } 27 } 28 29 /// <summary> 30 /// アタッチされたとき 31 /// </summary> 32 protected override void OnAttached() 33 { 34 base.OnAttached(); 35 36 this.AssociatedObject.Click += this.AssociatedObjectClick; 37 } 38 39 /// <summary> 40 /// デタッチされたとき 41 /// </summary> 42 protected override void OnDetaching() 43 { 44 this.AssociatedObject.Click -= this.AssociatedObjectClick; 45 46 base.OnDetaching(); 47 } 48 49 /// <summary> 50 /// クリックされたとき 51 /// </summary> 52 private void AssociatedObjectClick(object sender, RoutedEventArgs e) 53 { 54 if (this.NavigatePage == null) 55 { 56 return; 57 } 58 59 var button = (ButtonBase)sender; 60 var navigationService = GetNavigationService(button); 61 if (navigationService == null) 62 { 63 return; 64 } 65 66 // 現ページのパッケージURLを取得して相対パスを絶対パスに変換する。 67 // ※new Uri(((IUriContext)navigationWindow).BaseUri, this.NavigatePage) だと 68 //  ナビゲーションウィンドウXAMLからの相対パスになるので、サブディレクトリとの間で遷移できない。 69 var baseUri = BaseUriHelper.GetBaseUri(button); 70 var uri = new Uri(baseUri, this.NavigatePage); 71 72 // ナビゲート 73 navigationService.Navigate(uri, this.NavigateExtraData); 74 } 75 76 /// <summary> 77 /// ナビゲーションサービス取得 78 /// </summary> 79 /// <param name="element"></param> 80 /// <returns></returns> 81 protected virtual NavigationService GetNavigationService(DependencyObject element) 82 { 83 var window = Window.GetWindow(element); 84 if (window is NavigationWindow navigationWindow) 85 { 86 // NavigationWindow の場合 87 return navigationWindow.NavigationService; 88 } 89 90 var parent = element; 91 while ((parent = VisualTreeHelper.GetParent(parent)) != null) 92 { 93 if (parent is Frame frame) 94 { 95 // プレーンな(非 Navigation)Window で Frame を使用している場合 96 return frame.NavigationService; 97 } 98 } 99 100 return null; 101 } 102 }

試したこと1

ページ2のコードビハインドにNavigationService.LoadCompletedイベントで設定したパラメータを取得。
(MVVMで実装したいため、最終的にはViewModelでNavigationService.LoadCompletedの実装を行いたいが方法が、
わからなかったためテストとしてコードビハインドに記載)
結果は例外が発生。

試したコード

C#

1 public partial class Page2View : Page 2 { 3 public Page2View() 4 { 5 InitializeComponent(); 6 7 // ここでエラーが発生 8 NavigationService.LoadCompleted += NavigationService_LoadCompleted; 9 10 } 11 12 private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e) 13 { 14 string str = (string)e.ExtraData; 15 } 16 }

エラーメッセージ

型 'System.Reflection.TargetInvocationException' のハンドルされていない例外が PresentationFramework.dll で発生しました 追加情報: 呼び出しのターゲットが例外をスローしました。

試したこと2

NavigateButtonBehaiviorクラスのNavigateExtraDataPropertyに設定した値を取得
結果はNullが取得された。

C#

1 public partial class Page2View : Page 2 { 3 public Page2View() 4 { 5 InitializeComponent(); 6 7 // 結果はnullを取得 8 var para = new NavigateButtonBehaivior().NavigateExtraData; 9 10 } 11 }

補足

上記の実装方法がそもそも的を射ていないのか、コーディングミスなのかの判断もついていないため、
他に良い方法があるなど御座いましたらご教授いただきたいです。

TN8001👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

ナビゲーションの概要 - WPF | Microsoft Docs
でも注意がありますが、WPFだとNavigationServiceを複数持つことが可能なため、Page2ViewのコンストラクタではNavigationServiceを取得できないのだと思います(まだ決定できない)

Application.Navigatedか、NavigationWindowNavigationServiceを取得するかでしょうか?

cs

1using System.Diagnostics; 2using System.Windows; 3using System.Windows.Controls; 4using System.Windows.Navigation; 5 6namespace NavigationTest 7{ 8 public partial class Page2View : Page 9 { 10 public Page2View() 11 { 12 InitializeComponent(); 13 14 Application.Current.Navigated += Application_Navigated; 15 16 var w = Application.Current.MainWindow as NavigationWindow; 17 w.NavigationService.LoadCompleted += NavigationService_LoadCompleted; 18 } 19 20 private void Application_Navigated(object sender, NavigationEventArgs e) 21 { 22 Debug.WriteLine("Application_Navigated"); 23 Debug.WriteLine(e.ExtraData); 24 Application.Current.Navigated -= Application_Navigated; 25 } 26 27 private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e) 28 { 29 Debug.WriteLine("NavigationService_LoadCompleted"); 30 Debug.WriteLine(e.ExtraData); 31 var w = Application.Current.MainWindow as NavigationWindow; 32 w.NavigationService.LoadCompleted -= NavigationService_LoadCompleted; 33 } 34 } 35}

調べていて初めて知ったのですが、こういったものもあるようです(なにもわかっていません^^;
構造化ナビゲーションの概要 - WPF | Microsoft Docs
PageFunction<T> クラス (System.Windows.Navigation) | Microsoft Docs

MVVMに強いこだわりがあるなら、Prism Libraryなどに移行したほうが幸せかもしれません(NavigationWindowFrameはWPFではあまり使われていない印象です)

投稿2020/06/30 09:08

編集2024/04/13 00:27
TN8001

総合スコア9321

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

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

WTB_21

2020/06/30 13:42 編集

ご教授頂いた方法で解決することが出来ました。ありがとうございます。 別環境でご教授頂いた方法を試す際に気づいたのですが、NavigateButtonBehaivior クラスので使用している「Behavior<T>」は名前空間「System.Windows.Interactivity」の廃止により「Microsoft.Xaml.Behaviors」に変更されているのですね。 using部分の記載を省いたせいでご回答くださる際にお手を煩わせていたら申し訳ございません。 ↑ Nugetより「Microsoft.Xaml.Behaviors.Wpf」をインストールすることで解決することが出来ました。 構造化ナビゲーションとPageFunction<T> クラスについて初見でしたので勉強したいと思います。 Prism Libraryへの移行も検討したいと思います。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問