画面遷移先でパラメータの受け方がわからない
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 }
補足
上記の実装方法がそもそも的を射ていないのか、コーディングミスなのかの判断もついていないため、
他に良い方法があるなど御座いましたらご教授いただきたいです。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/30 13:42 編集