VB のたまご

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



Navigation6

  •  引き続き、Navigation です。 ここでは、他の画面に遷移した後で、インスタンスを自動的に破棄する方法を学習します。

  •  一度表示したら再度表示できなくしたい時に使えるのですが、具体的なシナリオが思いつきませんでした。 この機能を使うには、Prism.Regions.IRegionMemberLifetime インターフェースを実装して使います。

  •  このインターフェースには、KeepAlive プロパティというインスタンスを破棄するか維持するかを決める機能があります。 これが True だとインスタンスを維持する、False だと維持しない(破棄する)となります。

  • ' 非アクティブになったらインスタンスを破棄するかどうか
    ' true:破棄しない、false:破棄する
    Public ReadOnly Property KeepAlive As Boolean Implements IRegionMemberLifetime.KeepAlive
        Get
    
            Console.WriteLine($"{vbTab}AViewModel - KeepAlive, 非アクティブになったので、破棄します")
            Return False
    
        End Get
    End Property
    

  •  このサンプルを実行すると、2つのボタンが表示されています。 先に「BView へ遷移」ボタンですが、このボタンを押すたびに、BView が追加されていきます。 そして、「AView へ遷移」ボタンを押すと、AView が表示されますが、何回押しても AView は1つのままです。

  •  これは、2つ目の AView が追加されたと同時に、非アクティブになった今まで表示していた AView が破棄されてしまうので、 常に1つ分しか表示されない、という仕組みになります。

  • スポンサーリンク


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

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

  •  AViewModel.vb

  • Imports Prism.Mvvm
    Imports Prism.Regions
    
    Namespace ViewModels
    
        Public Class AViewModel
            Inherits BindableBase
            Implements INavigationAware, IRegionMemberLifetime
    
            ' 非アクティブになったらインスタンスを破棄するかどうか
            ' true:破棄しない、false:破棄する
            Public ReadOnly Property KeepAlive As Boolean Implements IRegionMemberLifetime.KeepAlive
                Get
    
                    Console.WriteLine($"{vbTab}AViewModel - KeepAlive, 非アクティブになったので、破棄します")
                    Return False
    
                End Get
            End Property
    
            ' 遷移先の画面として本画面のインスタンスを再利用するかどうか
            ' true: 本画面のインスタンスを再利用して表示、別インスタンスとして本画面を表示
            Public Function IsNavigationTarget(navigationContext As NavigationContext) As Boolean Implements INavigationAware.IsNavigationTarget
    
                Console.WriteLine($"{vbTab}AViewModel - IsNavigationTarget, 別画面に表示してください")
                Return False
    
            End Function
    
            ' 本画面に遷移する時の処理
            Public Sub OnNavigatedTo(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedTo
    
                'Console.WriteLine($"{vbTab}AViewModel - OnNavigatedTo")
    
            End Sub
    
            ' 本画面から離れる時の処理
            Public Sub OnNavigatedFrom(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedFrom
    
                'Console.WriteLine($"{vbTab}AViewModel - OnNavigatedFrom")
    
            End Sub
    
        End Class
    
    End Namespace
    

  •  BViewModel.vb

  • Imports Prism.Mvvm
    Imports Prism.Regions
    
    Namespace ViewModels
    
        Public Class BViewModel
            Inherits BindableBase
            Implements INavigationAware
    
            ' 遷移先の画面として本画面のインスタンスを再利用するかどうか
            ' true: 本画面のインスタンスを再利用して表示、別インスタンスとして本画面を表示
            Public Function IsNavigationTarget(navigationContext As NavigationContext) As Boolean Implements INavigationAware.IsNavigationTarget
    
                Console.WriteLine($"{vbTab}BViewModel - IsNavigationTarget, 別画面に表示してください")
                Return False
    
            End Function
    
            ' 本画面に遷移する時の処理
            Public Sub OnNavigatedTo(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedTo
    
                'Console.WriteLine($"{vbTab}BViewModel - OnNavigatedTo")
    
            End Sub
    
            ' 本画面から離れる時の処理
            Public Sub OnNavigatedFrom(navigationContext As NavigationContext) Implements INavigationAware.OnNavigatedFrom
    
                'Console.WriteLine($"{vbTab}BViewModel - OnNavigatedFrom")
    
            End Sub
    
        End Class
    
    End Namespace
    

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

  • <UserControl x:Class="Views.AView"
                 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>
            <TextBlock Text="View A" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Grid>
    
    </UserControl>
    

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

  • <UserControl x:Class="Views.BView"
                 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>
            <TextBlock Text="View B" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </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
    
        Public Sub Initialize() Implements IModule.Initialize
    
            Me.Container.RegisterTypeForNavigation(Of AView)()
            Me.Container.RegisterTypeForNavigation(Of BView)()
    
        End Sub
    
    End Class
    

    スポンサーリンク


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

  •  Window1ViewModel.vb

  • Imports Microsoft.Practices.Unity ' Dependency 属性
    Imports Prism.Mvvm
    Imports Prism.Commands
    Imports Prism.Regions
    Imports System.Collections.ObjectModel
    Imports System.Collections.Specialized
    
    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
    
            Private _Views As ObservableCollection(Of Object) = New ObservableCollection(Of Object)
            Public Property Views() As ObservableCollection(Of Object)
                Get
                    Return _Views
                End Get
                Set(ByVal value As ObservableCollection(Of Object))
                    Me.SetProperty(_Views, value)
                End Set
            End Property
    
            Public Property NavigateCommand As DelegateCommand(Of String)
    
            Private ReadOnly Manager As IRegionManager
    
            ' コンストラクタ
            Public Sub New(_manager As IRegionManager)
    
                ' リージョン区画のコレクション管理イベントを購読
                Me.Manager = _manager
                AddHandler Me.Manager.Regions.CollectionChanged, AddressOf Me.Regions_CollectionChanged
    
                Me.NavigateCommand = New DelegateCommand(Of String)(AddressOf Me.Navigate)
    
            End Sub
    
            ' 1つ分のリージョン区画で管理している、インジェクション中の画面コレクション管理イベントを購読
            Private Sub Regions_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
    
                If e.Action = NotifyCollectionChangedAction.Add Then
    
                    Console.WriteLine($"Window1ViewModel - Regions_CollectionChanged, 登録されたRegion: {e.NewItems(0)} のコレクションイベントを購読")
                    Dim region = TryCast(e.NewItems(0), IRegion)
                    AddHandler region.Views.CollectionChanged, AddressOf Me.Views_CollectionChanged
    
                End If
    
            End Sub
    
            ' インジェクション中の画面コレクションに変更があった時の処理
            Private Sub Views_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
    
                If e.Action = NotifyCollectionChangedAction.Add Then
    
                    Dim viewName = e.NewItems(0).GetType().Name
                    Console.WriteLine($"Window1ViewModel - Views_CollectionChanged, {viewName} をコレクションに追加")
                    Me.Views.Add(viewName)
    
                ElseIf e.Action = NotifyCollectionChangedAction.Remove Then
    
                    Dim viewName = e.OldItems(0).GetType().Name
                    Console.WriteLine($"Window1ViewModel - Views_CollectionChanged, {viewName} をコレクションに削除")
                    Me.Views.Remove(viewName)
    
                End If
    
                ' 変更後の現在値を表示
                Dim items = String.Join(", ", Me.Views)
                Console.WriteLine($"Window1ViewModel - Views_CollectionChanged, 現在値: {items} ")
    
            End Sub
    
            ' 画面を遷移
            Private Sub Navigate(viewName As String)
    
                If Not String.IsNullOrWhiteSpace(viewName) Then
    
                    Console.WriteLine($"Window1ViewModel - Navigate, {viewName} に遷移")
                    Me.Manager.RequestNavigate("ContentRegion", viewName)
    
                End If
    
            End Sub
    
        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">
    
        <DockPanel LastChildFill="True">
    
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5">
                
                <Button 
                    Content="AView へ遷移" 
                    Command="{Binding NavigateCommand}" 
                    CommandParameter="AView" 
                    Margin="5" />
    
                <Button 
                    Content="BView へ遷移" 
                    Command="{Binding NavigateCommand}" 
                    CommandParameter="BView" 
                    Margin="5" />
    
            </StackPanel>
    
            <ItemsControl ItemsSource="{Binding Views}" Margin="5">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border Background="LightBlue" Height="50" Width="50" Margin="2">
                            <TextBlock Text="{Binding}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
    
            <ContentControl 
                prism:RegionManager.RegionName="ContentRegion"
                Margin="5" />
    
        </DockPanel>
    
    </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