VB のたまご

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



Region4

  •  引き続き、Region です。 今回は、2つの各画面を表示したり非表示にしたり切り替える処理を学習します。

  •  あらかじめ、ブートストラッパー内で、ユーザーコントロールを Unity コンテナに登録しておきます。 今回は、AView と BView というユーザーコントロールを作成しています。

  • Protected Overrides Sub ConfigureContainer()
        MyBase.ConfigureContainer()
    
        Me.Container.RegisterType(Of Object, AView)("AView")
        Me.Container.RegisterType(Of Object, BView)("BView")
    
    End Sub
    

  •  ViewModel では、画面のインスタンスを保持しつつ、ボタンを押して表示を切り替える構成です。 ポイントを3つに分けて説明します。

  • スポンサーリンク


  •  1つ目
  •  ViewModel のメンバーとして3つ用意します。

  • Private Region As IRegion
    Private AViewObject As Object
    Private BViewObject As Object
    

  •  IRegion プロパティには、IRegionManager から ContentRegion 区画に関する管理データを受け取って、 各ボタン処理内で、区画内の画面オブジェクトを切り替えるために使用します。

  •  AViewObject, BViewObject はそれぞれユーザーコントロールのインスタンスを扱うために使用します。 今回は、同じ参照データであることが重要なポイントです。

  •  2つ目
  •  InitializeCommand コマンドを使って、初期化処理を行います。 ViewModel のコンストラクタ処理のタイミングでは、ContentRegion 区画はまだ割り当たっていません。 Dependency 属性を付けて取得しようとしたときの、IUnityContainer, IRegionManager も同様ですね。

  •  そのため、もっと遅いタイミングのイベント、View の ContentRendered イベント辺りなら、ContentRegion 区画の割り当てが完了しているので、 このイベント発生のタイミングで【準備が整ってからの初期化処理】用のコマンドを自動実行させるようにしています。

  • <Dependency> Public Property Container As IUnityContainer
    <Dependency> Public Property Manager As IRegionManager
    Public Property InitializeCommand As DelegateCommand
    
    ' コンストラクタ
    Public Sub New()
    
        Me.InitializeCommand =
            New DelegateCommand(Sub()
    
                                    Me.AViewObject = Me.Container.Resolve(Of Object)("AView")
                                    Me.BViewObject = Me.Container.Resolve(Of Object)("BView")
                                    Me.Region = Me.Manager.Regions("ContentRegion")
    
                                    Me.Region.Add(Me.AViewObject)
                                    Me.Region.Add(Me.BViewObject)
    
                                End Sub)
    
    End Sub
    

  •  ここでやりたい初期化処理は、AView と BView のインスタンス生成と、ContentRegion 区画に関する管理データを取得することです。 1つ目で説明した各メンバーに、インスタンスをセットすることですね。

  •  また、あらかじめ、ContentRegion 区画には、AView と BView のインスタンスを追加しておきます。 この処理をしても、まだ表示はされません。

  •  3つ目
  •  最後に、画面切り替え用のコマンドを準備します。 IRegion インターフェースの Activate メソッドで指定した画面を表示したり、Deactivate メソッドで指定した画面を非表示にしたりできます。

  • Public Property ActiveAViewCommand As DelegateCommand
    Public Property DeactiveAViewCommand As DelegateCommand
    Public Property ActiveBViewCommand As DelegateCommand
    Public Property DeactiveBViewCommand As DelegateCommand
    
    ' コンストラクタ
    Public Sub New()
    
        Me.ActiveAViewCommand =
            New DelegateCommand(Sub() Me.Region.Activate(Me.AViewObject))
    
        Me.DeactiveAViewCommand =
            New DelegateCommand(Sub() Me.Region.Deactivate(Me.AViewObject))
    
        Me.ActiveBViewCommand =
            New DelegateCommand(Sub() Me.Region.Activate(Me.BViewObject))
    
        Me.DeactiveBViewCommand =
            New DelegateCommand(Sub() Me.Region.Deactivate(Me.BViewObject))
    
    End Sub
    

  •  このサンプルを実行すると、ボタンが4つ表示されます。 それぞれのボタンを押すと、各画面を表示、または非表示に切り替えます。

  • スポンサーリンク


  •  それでは、以下ソース全体です。
  •  今回は、WPF アプリケーションプロジェクトだけです。

  •  Window1ViewModel.vb

  • Imports Microsoft.Practices.Unity
    Imports Prism.Unity
    Imports Prism.Regions
    Imports Prism.Mvvm
    Imports Prism.Commands
    Imports Prism
    
    Namespace ViewModels
    
        Public Class Window1ViewModel
            Inherits BindableBase
    
            Private Region As IRegion
            Private AViewObject As Object
            Private BViewObject As Object
    
            <Dependency> Public Property Container As IUnityContainer
            <Dependency> Public Property Manager As IRegionManager
            Public Property InitializeCommand As DelegateCommand
            Public Property ActiveAViewCommand As DelegateCommand
            Public Property DeactiveAViewCommand As DelegateCommand
            Public Property ActiveBViewCommand As DelegateCommand
            Public Property DeactiveBViewCommand As DelegateCommand
    
            ' コンストラクタ
            Public Sub New()
    
                Me.InitializeCommand =
                    New DelegateCommand(Sub()
    
                                            Me.AViewObject = Me.Container.Resolve(Of Object)("AView")
                                            Me.BViewObject = Me.Container.Resolve(Of Object)("BView")
                                            Me.Region = Me.Manager.Regions("ContentRegion")
    
                                            Me.Region.Add(Me.AViewObject)
                                            Me.Region.Add(Me.BViewObject)
    
                                        End Sub)
    
                Me.ActiveAViewCommand =
                    New DelegateCommand(Sub() Me.Region.Activate(Me.AViewObject))
    
                Me.DeactiveAViewCommand =
                    New DelegateCommand(Sub() Me.Region.Deactivate(Me.AViewObject))
    
                Me.ActiveBViewCommand =
                    New DelegateCommand(Sub() Me.Region.Activate(Me.BViewObject))
    
                Me.DeactiveBViewCommand =
                    New DelegateCommand(Sub() Me.Region.Deactivate(Me.BViewObject))
    
            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"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
            mc:Ignorable="d"
            Title="Window1" Height="350" Width="525">
    
        <!-- インジェクションが終わった後の初期化処理 -->
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="ContentRendered">
                <prism:InvokeCommandAction Command="{Binding InitializeCommand}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        
        <DockPanel LastChildFill="True">
    
            <StackPanel>
                <Button Content="AView を表示" Command="{Binding ActiveAViewCommand}" />
                <Button Content="AView を非表示" Command="{Binding DeactiveAViewCommand}" />
                <Button Content="BView を表示" Command="{Binding ActiveBViewCommand}" />
                <Button Content="BView を非表示" Command="{Binding DeactiveBViewCommand}" />
            </StackPanel>
    
            <ContentControl prism:RegionManager.RegionName="ContentRegion" HorizontalAlignment="Center" VerticalAlignment="Center" />
    
        </DockPanel>
    
    </Window>
    

  •  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:WpfApplication1.Views"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        
        <Grid>
            <TextBlock Text="View A" FontSize="40" />
        </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:WpfApplication1.Views"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        
        <Grid>
            <TextBlock Text="View B" FontSize="40" />
        </Grid>
        
    </UserControl>
    

  •  Bootstrapper.vb

  • Imports Microsoft.Practices.Unity
    Imports Prism.Unity
    Imports Prism.Modularity
    Imports WpfApplication1.Views
    
    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
    
        ' コンテナに画面を登録、ViewModel から呼べるように、Object 型と画面名を登録
        Protected Overrides Sub ConfigureContainer()
            MyBase.ConfigureContainer()
    
            Me.Container.RegisterType(Of Object, AView)("AView")
            Me.Container.RegisterType(Of Object, BView)("BView")
    
        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