VB のたまご

作成日: 2017/05/14, 更新日: 2017/05/14



Navigation7

  •  引き続き、Navigation です。 遷移処理を行うと直前の履歴を覚えることができます。 この履歴情報を使うと、RequestNavigate メソッドを使わなくても、再遷移したり戻ったりと移動することができるようになります。

  • イメージ
  •  これは今回のサンプルの遷移構成です。 そして、履歴管理は Prism.Regions.IRegionNavigationJournal インターフェースを使っておこないます。 サンプルでは、OnNavigatedTo メソッドのタイミングで、受け取った NavigationContext データから履歴データを取得しています。

  • Private Journal As IRegionNavigationJournal
    Public Property GoForwardCommand As DelegateCommand
    
    Public Sub OnNavigatedTo(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedTo
    
        Me.Journal = navigationContext.NavigationService.Journal
        Me.GoForwardCommand.RaiseCanExecuteChanged()
    
    End Sub
    

  •  履歴データを使った遷移は、コマンドの処理として使っています。

  • ' コンストラクタ
    Public Sub New()
        Me.GoForwardCommand = New DelegateCommand(AddressOf Me.GoForward, AddressOf Me.CanGoForward)
    End Sub
    
    Private Sub GoForward()
        Me.Journal.GoForward()
    End Sub
    
    Private Function CanGoForward() As Boolean
        Return (Me.Journal IsNot Nothing) AndAlso (Me.Journal.CanGoForward)
    End Function
    

  •  ただし、履歴データは一度 RequestNavigate メソッドで移動しないと生成されないため、初回は RequestNavigate メソッドによる遷移が必要となります。

  • Public Property PersonSelectedCommand As DelegateCommand(Of PersonModel)
    
    ' コンストラクタ
    Public Sub New()
        Me.PersonSelectedCommand = New DelegateCommand(Of PersonModel)(AddressOf Me.PersonSelected)
    End Sub
    
    Private Sub PersonSelected(person As PersonModel)
    
        Dim parameters = New NavigationParameters
        parameters.Add(NameOf(person), person)
    
        If person IsNot Nothing Then
            ' クリックして遷移することで、遷移履歴が生まれる
            Me.Manager.RequestNavigate("ContentRegion", "PersonDetail", parameters)
        End If
    
    End Sub
    

  •  戻ってくる時も同様の手順です。NavigationContext データから履歴データを取得して戻ります。

  • Public Property GoBackCommand As DelegateCommand
    Private Journal As IRegionNavigationJournal
    
    Public Sub OnNavigatedTo(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedTo
        Me.Journal = navigationContext.NavigationService.Journal
    End Sub
    
    ' コンストラクタ
    Public Sub New()
        Me.GoBackCommand = New DelegateCommand(AddressOf Me.GoBack)
    End Sub
    
    Private Sub GoBack()
        Me.Journal.GoBack()
    End Sub
    

  •  このサンプルを実行すると、リストボックスと押せないボタンが表示されます。 リストボックス内にある任意の項目を選択すると詳細画面に切り替わります。 「戻る」ボタンを押すと画面が元の画面に戻ります。

  •  戻ってくると「進む」ボタンが押せるようになっています。 ここで「進む」ボタンを押すと、先程遷移した詳細画面に遷移することができます。

  • スポンサーリンク


  •  それでは、以下ソース全体です。

  •  クラスライブラリプロジェクト

  •  PersonModel.vb

  • Imports Prism.Mvvm
    
    Namespace Models
    
        Public Class PersonModel
            Inherits BindableBase
    
            Private _FirstName As String
            Public Property FirstName() As String
                Get
                    Return _FirstName
                End Get
                Set(ByVal value As String)
                    Me.SetProperty(_FirstName, value)
                End Set
            End Property
    
            Private _LastName As String
            Public Property LastName() As String
                Get
                    Return _LastName
                End Get
                Set(ByVal value As String)
                    Me.SetProperty(_LastName, value)
                End Set
            End Property
    
            Private _Age As Integer
            Public Property Age() As Integer
                Get
                    Return _Age
                End Get
                Set(ByVal value As Integer)
                    Me.SetProperty(_Age, value)
                End Set
            End Property
    
            Private _LastUpdated As DateTime?
            Public Property LastUpdated() As DateTime?
                Get
                    Return _LastUpdated
                End Get
                Set(ByVal value As DateTime?)
                    Me.SetProperty(_LastUpdated, value)
                End Set
            End Property
    
            Public Overrides Function ToString() As String
                Return $"{Me.LastName}, {Me.FirstName}"
            End Function
    
        End Class
    
    End Namespace
    

  •  PersonDetailViewModel.vb

  • Imports Prism.Mvvm
    Imports Prism.Commands
    Imports Prism.Regions
    Imports ClassLibrary1.Models
    
    Namespace ViewModels
    
        Public Class PersonDetailViewModel
            Inherits BindableBase
            Implements INavigationAware
    
            Private _SelectedPerson As PersonModel
            Public Property SelectedPerson() As PersonModel
                Get
                    Return _SelectedPerson
                End Get
                Set(ByVal value As PersonModel)
                    Me.SetProperty(_SelectedPerson, value)
                End Set
            End Property
    
            Public Property GoBackCommand As DelegateCommand
            Private Journal As IRegionNavigationJournal
    
            ' コンストラクタ
            Public Sub New()
                Me.GoBackCommand = New DelegateCommand(AddressOf Me.GoBack)
            End Sub
    
            Private Sub GoBack()
    
                Console.WriteLine($"PersonDetailViewModel - GoBack, before, Journal.CurrentEntry = {Me.Journal?.CurrentEntry}")
                Console.WriteLine($"PersonDetailViewModel - GoBack, before, Journal.CanGoForward = {Me.Journal?.CanGoForward}")
                Console.WriteLine($"PersonDetailViewModel - GoBack, before, Journal.CanGoBack = {Me.Journal?.CanGoBack}")
    
                ' GoBack メソッドを呼び出すことで、遷移前の画面に戻ります
                ' 1.PersonListViewModel/IsNavigationTarget メソッド
                ' 2.PersonListViewModel/OnNavigatedTo メソッド
                Me.Journal.GoBack()
    
                ' Journal が PersonDetail から PersonList に切り替わります
                Console.WriteLine($"PersonDetailViewModel - GoBack, after, Journal.CurrentEntry = {Me.Journal?.CurrentEntry}")
                Console.WriteLine($"PersonDetailViewModel - GoBack, after, Journal.CanGoForward = {Me.Journal?.CanGoForward}")
                Console.WriteLine($"PersonDetailViewModel - GoBack, after, Journal.CanGoBack = {Me.Journal?.CanGoBack}")
    
            End Sub
    
            Public Function IsNavigationTarget(navigationContext As NavigationContext) As Boolean Implements INavigationAware.IsNavigationTarget
    
                Dim person = TryCast(navigationContext.Parameters("person"), PersonModel)
                If person IsNot Nothing Then
                    Return (Me.SelectedPerson IsNot Nothing) AndAlso (Me.SelectedPerson.LastName = person.LastName)
                Else
                    Return True
                End If
    
            End Function
    
            Public Sub OnNavigatedTo(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedTo
    
                Me.Journal = navigationContext.NavigationService.Journal
    
                Dim person = TryCast(navigationContext.Parameters("person"), PersonModel)
                If person IsNot Nothing Then
                    Me.SelectedPerson = person
                End If
    
            End Sub
    
            Public Sub OnNavigatedFrom(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedFrom
    
            End Sub
    
        End Class
    
    End Namespace
    

  •  PersonListViewModel.vb

  • Imports Prism.Mvvm
    Imports Prism.Commands
    Imports Prism.Regions
    Imports System.Collections.ObjectModel
    Imports ClassLibrary1.Models
    
    Namespace ViewModels
    
        Public Class PersonListViewModel
            Inherits BindableBase
            Implements INavigationAware
    
            Private Manager As IRegionManager
            Private Journal As IRegionNavigationJournal
    
            Public Property PersonSelectedCommand As DelegateCommand(Of PersonModel)
            Public Property GoForwardCommand As DelegateCommand
    
            Private _People As ObservableCollection(Of PersonModel)
            Public Property People() As ObservableCollection(Of PersonModel)
                Get
                    Return _People
                End Get
                Set(ByVal value As ObservableCollection(Of PersonModel))
                    Me.SetProperty(_People, value)
                End Set
            End Property
    
            ' コンストラクタ
            Public Sub New(_manager As IRegionManager)
    
                Me.Manager = _manager
    
                Me.PersonSelectedCommand = New DelegateCommand(Of PersonModel)(AddressOf Me.PersonSelected)
                Me.GoForwardCommand = New DelegateCommand(AddressOf Me.GoForward, AddressOf Me.CanGoForward)
    
                Me.CreatePeople()
    
            End Sub
    
            Private Sub PersonSelected(person As PersonModel)
    
                Dim parameters = New NavigationParameters
                parameters.Add(NameOf(person), person)
    
                If person IsNot Nothing Then
                    ' クリックして遷移することで、遷移履歴が生まれる
                    Me.Manager.RequestNavigate("ContentRegion", "PersonDetail", parameters)
                End If
    
            End Sub
    
            Private Sub GoForward()
    
                Console.WriteLine($"PersonListViewModel - GoForward, before, Journal.CurrentEntry = {Me.Journal?.CurrentEntry}")
                Console.WriteLine($"PersonListViewModel - GoForward, before, Journal.CanGoForward = {Me.Journal?.CanGoForward}")
                Console.WriteLine($"PersonListViewModel - GoForward, before, Journal.CanGoBack = {Me.Journal?.CanGoBack}")
    
                ' GoForward メソッドを呼び出すことで、遷移後の画面に進みます
                ' 1.PersonDetailViewModel/IsNavigationTarget メソッド
                ' 2.PersonDetailViewModel/OnNavigatedTo メソッド
                Me.Journal.GoForward()
    
                ' Journal が PersonList から PersonDetail に切り替わります
                Console.WriteLine($"PersonListViewModel - GoForward, after, Journal.CurrentEntry = {Me.Journal?.CurrentEntry}")
                Console.WriteLine($"PersonListViewModel - GoForward, after, Journal.CanGoForward = {Me.Journal?.CanGoForward}")
                Console.WriteLine($"PersonListViewModel - GoForward, after, Journal.CanGoBack = {Me.Journal?.CanGoBack}")
    
            End Sub
    
            Private Function CanGoForward() As Boolean
                Return (Me.Journal IsNot Nothing) AndAlso (Me.Journal.CanGoForward)
            End Function
    
            ' 初期値を登録
            Private Sub CreatePeople()
    
                Dim items = New List(Of PersonModel)
                For i As Integer = 0 To 10
                    items.Add(New PersonModel With
                              {
                              .FirstName = $"First {i}",
                              .LastName = $"Last {i}",
                              .Age = i
                              })
                Next
    
                Me.People = New ObservableCollection(Of PersonModel)(items)
    
            End Sub
    
            Public Function IsNavigationTarget(navigationContext As NavigationContext) As Boolean Implements INavigationAware.IsNavigationTarget
                Return True
            End Function
    
            Public Sub OnNavigatedTo(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedTo
    
                Me.Journal = navigationContext.NavigationService.Journal
                Me.GoForwardCommand.RaiseCanExecuteChanged()
    
            End Sub
    
            Public Sub OnNavigatedFrom(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedFrom
    
            End Sub
    
        End Class
    
    End Namespace
    

  •  PersonDetail.xaml
  •  画面クラスのコードビハインドには、名前空間の追加以外、処理はありません。

  • <UserControl x:Class="Views.PersonDetail"
                 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" 
                 xmlns:local="clr-namespace:ClassLibrary1.Views"
                 xmlns:prism="http://prismlibrary.com/"
                 prism:ViewModelLocator.AutoWireViewModel="True"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        
        <Grid Background="White">
    
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
    
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
    
            <!-- First Name -->
            <TextBlock Text="First Name:" Margin="5" />
            <TextBlock Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.FirstName}" />
    
            <!-- Last Name -->
            <TextBlock Grid.Row="1" Text="Last Name:" Margin="5" />
            <TextBlock Grid.Row="1" Grid.Column="1"  Margin="5" Text="{Binding SelectedPerson.LastName}" />
    
            <!-- Age -->
            <TextBlock Grid.Row="2" Text="Age:" Margin="5"/>
            <TextBlock Grid.Row="2" Grid.Column="1"  Margin="5" Text="{Binding SelectedPerson.Age}"/>
    
            <!-- ナビゲーションの遷移履歴があれば、遷移履歴データを使って再遷移する(戻る) -->
            <Button 
                Grid.Row="3" Grid.ColumnSpan="2" 
                Content="戻る"
                Command="{Binding GoBackCommand}" 
                HorizontalAlignment="Center" 
                Margin="10" 
                Width="75" />
    
        </Grid>
        
    </UserControl>
    

  •  PersonList.xaml
  •  画面クラスのコードビハインドには、名前空間の追加以外、処理はありません。

  • <UserControl x:Class="Views.PersonList"
                 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" 
                 xmlns:local="clr-namespace:ClassLibrary1.Views"
                 xmlns:prism="http://prismlibrary.com/"
                 prism:ViewModelLocator.AutoWireViewModel="True"
                 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        
        <Grid Background="White" Margin="10">
    
            <Grid.RowDefinitions>
                <RowDefinition Height="100" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
    
            <!-- 詳細画面に遷移 -->
            <ListBox Name="listbox1" ItemsSource="{Binding People}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <prism:InvokeCommandAction
                            Command="{Binding PersonSelectedCommand}"
                            CommandParameter="{Binding ElementName=listbox1, Path=SelectedItem}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ListBox>
    
            <!-- ナビゲーションの遷移履歴があれば、遷移履歴データを使って再遷移する -->
            <Button
                Grid.Row="1"
                Margin="10"
                Width="75"
                Content="進む"
                Command="{Binding GoForwardCommand}" />
    
        </Grid>
        
    </UserControl>
    

  •  ClassLibrary1Module.vb

  • Imports Microsoft.Practices.Unity
    Imports Prism.Unity
    Imports Prism.Regions
    Imports Prism.Modularity
    Imports ClassLibrary1.Views
    
    Public Class ClassLibrary1Module
        Implements IModule
    
        <Dependency>
        Public Property Container As IUnityContainer
    
        <Dependency>
        Public Property Manager As IRegionManager
    
        Public Sub Initialize() Implements IModule.Initialize
    
            Me.Container.RegisterTypeForNavigation(Of PersonList)()
            Me.Container.RegisterTypeForNavigation(Of PersonDetail)()
    
            Me.Manager.RequestNavigate("ContentRegion", "PersonList")
    
        End Sub
    
    End Class
    

    スポンサーリンク


  •  WPF アプリケーションプロジェクト

  •  Window1ViewModel.vb

  • Imports Prism.Mvvm
    
    Namespace ViewModels
    
        Public Class Window1ViewModel
            Inherits BindableBase
    
            Private _Title As String = "Prism Unity Application"
            Public Property Title() As String
                Get
                    Return _Title
                End Get
                Set(ByVal value As String)
                    Me.SetProperty(_Title, value)
                End Set
            End Property
    
        End Class
    
    End Namespace
    

  •  Window1.xaml
  •  画面クラスのコードビハインドには、名前空間の追加以外、処理はありません。

  • <Window x:Class="Views.Window1"
            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"
            xmlns:local="clr-namespace:WpfApplication1.Views"
            xmlns:prism="http://prismlibrary.com/"
            prism:ViewModelLocator.AutoWireViewModel="True"
            mc:Ignorable="d"
            Title="{Binding Title}" Height="350" Width="525">
    
        <Grid>
            <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        </Grid>
    
    </Window>
    

  •  Bootstrapper.vb

  • Imports Microsoft.Practices.Unity
    Imports Prism.Unity
    Imports Prism.Modularity
    Imports WpfApplication1.Views
    Imports ClassLibrary1
    
    Public Class Bootstrapper
        Inherits UnityBootstrapper
    
        ' Shell 担当になる View のインスタンスを返却
        Protected Overrides Function CreateShell() As DependencyObject
            Return Me.Container.Resolve(Of Window1)
        End Function
    
        ' Shell 担当になる View を表示
        Protected Overrides Sub InitializeShell()
            Application.Current.MainWindow.Show()
        End Sub
    
        ' モジュールカタログにモジュール情報を登録
        Protected Overrides Sub ConfigureModuleCatalog()
    
            Dim catalog = CType(Me.ModuleCatalog, ModuleCatalog)
            catalog.AddModule(GetType(ClassLibrary1Module))
    
        End Sub
    
    End Class
    

  •  Application.xaml.vb
  •  ※Application.xaml では、【StartupUri="MainWindow.xaml"】を削除しています。

  • Class Application
    
        ' Startup、Exit、DispatcherUnhandledException などのアプリケーション レベルのイベントは、
        ' このファイルで処理できます。
    
        Protected Overrides Sub OnStartup(e As StartupEventArgs)
            MyBase.OnStartup(e)
    
            ' Unity 管理による Prism アプリケーションの起動制御処理を実行
            Dim boot = New Bootstrapper
            boot.Run()
    
        End Sub
    
    End Class