VB のたまご

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



CustomConfirmationRequest

  •  今回は、リスト項目から1つを選択するモーダル画面の表示方法を学習します。 渡すデータ形式や、表示する画面構成は独自形式ですが、全体の流れは今までと変わりません。

  • スポンサーリンク


  •  まずは、InteractionRequest に渡すインターフェースを作成します。 ここでは、選択中の項目を扱う SelectedItem プロパティをメンバーとするインターフェースを作成しています。

  • Public Interface ICustomConfirmation
        Inherits IConfirmation
    
        Property SelectedItem As String
    
    End Interface
    

  •  続いて、InteractionRequest クラスの Raise メソッドを呼び出して、View へ依頼をかける際に渡すクラスです。 このクラスは先程作成した ICustomConfirmation インターフェースを実装したクラスです。 この中では、表示したい全項目の生成と選択した項目を保持する2つのプロパティを定義しています。

  • Public Class CustomConfirmation
        Inherits Confirmation
        Implements ICustomConfirmation
    
        Public Property Items As IList(Of String)
        Public Property SelectedItem As String Implements ICustomConfirmation.SelectedItem
    
        Public Sub New()
    
            Me.Items = New List(Of String)
            Me.SelectedItem = Nothing
    
            For Each index In Enumerable.Range(1, 6)
                Me.Items.Add($"Item{index}")
            Next
    
        End Sub
    
    End Class
    

  •  続いて、ViewModel に、前回同様に通知依頼を指示する処理を記載していきます。 InteractionRequest クラスのジェネリック引数には ICustomConfirmation を指定しているところに注目です。

  • Public Property RequestMessage As InteractionRequest(Of ICustomConfirmation)
    Public Property RequestCommand As DelegateCommand
    
    ' コンストラクタ
    Public Sub New()
    
        Me.Title = "Prism Unity Application"
        Me.RequestMessage = New InteractionRequest(Of ICustomConfirmation)
        Me.RequestCommand = New DelegateCommand(AddressOf Me.ShowMessage)
    
    End Sub
    
    Private Sub ShowMessage()
    
        Dim message = New CustomConfirmation With {.Title = "カスタム画面の確認", .Content = "カスタム画面の確認メッセージです"}
        Me.RequestMessage.Raise(message, AddressOf Me.ShowMessageCallback)
    
    End Sub
    
    Private Sub ShowMessageCallback(message As ICustomConfirmation)
    
        If message.Confirmed AndAlso message.SelectedItem IsNot Nothing Then
            Me.Title = $"選択した項目:{message.SelectedItem}"
        Else
            Me.Title = "キャンセルボタンを押したか、未選択です"
        End If
    
    End Sub
    

  •  続いて、View で待機する処理を記載します。 RequestMessage メンバーをバインドして通知を待ちます。 独自画面に変えたい場合は、PopupWindowAction クラスの WindowContent プロパティに CustomView ユーザーコントロールを指定します。

  • <i:Interaction.Triggers>
    
        <prism:InteractionRequestTrigger SourceObject="{Binding RequestMessage}">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowContent>
                    <local:CustomView />
                </prism:PopupWindowAction.WindowContent>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>
    
    </i:Interaction.Triggers>
    

  •  最後に独自画面です。 View は省略して、バインドする ViewModel についてです。 この ViewModel では通知画面として成り立つために、IInteractionRequestAware インターフェースを実装します。

  •  Notification プロパティと FinishInteraction プロパティの2つは、後からインスタンスがインジェクションされるメンバーで、 Notification データには、呼び出し時に渡されてきたデータがセットされます。 FinishInteraction アクションは、画面を閉じる際に実行するアクションがセットされています。

  • Private _Notification As ICustomConfirmation
    Public Property Notification As INotification Implements IInteractionRequestAware.Notification
        Get
            Return _Notification
        End Get
        Set(value As INotification)
            Me.SetProperty(_Notification, CType(value, ICustomConfirmation))
        End Set
    End Property
    
    Private _FinishInteraction As Action
    Public Property FinishInteraction As Action Implements IInteractionRequestAware.FinishInteraction
        Get
            Return _FinishInteraction
        End Get
        Set(value As Action)
            Me.SetProperty(_FinishInteraction, value)
        End Set
    End Property
    

  •  続いて、複数項目から選択した項目である SelectedItem プロパティと、選択を決定するコマンドと、キャンセルするコマンドを定義します。 コマンド処理では、それぞれ Notification プロパティに任意の値をセットしていますが、これは、 表示する時に受け取るデータであると同時に、返却するデータでもあります。 各値を適切に更新した後、画面を閉じるアクションを実行して、画面を閉じています。

  • Public Property SelectedItem As String
    Public Property SelectedItemCommand As DelegateCommand
    Public Property CancelCommand As DelegateCommand
    
    ' コンストラクタの後で、Action プロパティと INotification プロパティにインジェクションされる
    ' コンストラクタ・インジェクションしていないし Dependency 属性も付けていないが、インジェクションされるみたい
    Public Sub New()
    
        Me.SelectedItemCommand = New DelegateCommand(AddressOf Me.Accept)
        Me.CancelCommand = New DelegateCommand(AddressOf Me.Cancel)
    
    End Sub
    
    Private Sub Accept()
    
        Me._Notification.SelectedItem = Me.SelectedItem
        Me._Notification.Confirmed = True
        Me.FinishInteraction?.Invoke()
    
    End Sub
    
    Private Sub Cancel()
    
        Me._Notification.SelectedItem = Nothing
        Me._Notification.Confirmed = False
        Me.FinishInteraction?.Invoke()
    
    End Sub
    

  •  このサンプルを実行すると、ボタンが表示されるのでボタンを押すと、独自作成した画面が表示されます。 この画面では、任意の項目を選択して「選択」ボタンを押すか「キャンセル」ボタンを押すことができます。 それぞれのボタンを押すことで、分岐別のコールバック処理が実行されて、タイトルが変更されます。

  • スポンサーリンク


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

  •  ICustomConfirmation.vb

  • Imports Prism.Interactivity.InteractionRequest
    
    Namespace Notifications
    
        Public Interface ICustomConfirmation
            Inherits IConfirmation
    
            Property SelectedItem As String
    
        End Interface
    
    End Namespace
    

  •  CustomConfirmation.vb

  • Imports Prism.Interactivity.InteractionRequest
    
    Namespace Notifications
    
        Public Class CustomConfirmation
            Inherits Confirmation
            Implements ICustomConfirmation
    
            Public Property Items As IList(Of String)
            Public Property SelectedItem As String Implements ICustomConfirmation.SelectedItem
    
            Public Sub New()
    
                Me.Items = New List(Of String)
                Me.SelectedItem = Nothing
    
                For Each index In Enumerable.Range(1, 6)
                    Me.Items.Add($"Item{index}")
                Next
    
            End Sub
    
        End Class
    
    End Namespace
    

  •  CustomViewModel.vb

  • Imports Prism.Mvvm
    Imports Prism.Commands
    Imports Prism.Interactivity.InteractionRequest
    Imports WpfApplication1.Notifications
    
    Namespace ViewModels
    
        Public Class CustomViewModel
            Inherits BindableBase
            Implements IInteractionRequestAware
    
            Public Property SelectedItem As String
            Public Property SelectedItemCommand As DelegateCommand
            Public Property CancelCommand As DelegateCommand
    
            Private _Notification As ICustomConfirmation
            Public Property Notification As INotification Implements IInteractionRequestAware.Notification
                Get
                    Return _Notification
                End Get
                Set(value As INotification)
                    Me.SetProperty(_Notification, CType(value, ICustomConfirmation))
                End Set
            End Property
    
            Private _FinishInteraction As Action
            Public Property FinishInteraction As Action Implements IInteractionRequestAware.FinishInteraction
                Get
                    Return _FinishInteraction
                End Get
                Set(value As Action)
                    Me.SetProperty(_FinishInteraction, value)
                End Set
            End Property
    
            ' コンストラクタの後で、Action プロパティと INotification プロパティにインジェクションされる
            ' コンストラクタ・インジェクションしていないし Dependency 属性も付けていないが、インジェクションされるみたい
            Public Sub New()
    
                Me.SelectedItemCommand = New DelegateCommand(AddressOf Me.Accept)
                Me.CancelCommand = New DelegateCommand(AddressOf Me.Cancel)
    
            End Sub
    
            Private Sub Accept()
    
                Me._Notification.SelectedItem = Me.SelectedItem
                Me._Notification.Confirmed = True
                Me.FinishInteraction?.Invoke()
    
            End Sub
    
            Private Sub Cancel()
    
                Me._Notification.SelectedItem = Nothing
                Me._Notification.Confirmed = False
                Me.FinishInteraction?.Invoke()
    
            End Sub
    
        End Class
    
    End Namespace
    

  •  Window1ViewModel.vb

  • Imports Prism.Mvvm
    Imports Prism.Commands
    Imports Prism.Interactivity.InteractionRequest
    Imports WpfApplication1.Notifications
    
    Namespace ViewModels
    
        ' 独自画面も同じように、ViewModel で InteractionRequest クラスの準備(依頼の指示)、
        ' View で InteractionRequestTrigger トリガー&アクションを準備(依頼された画面の表示)して、
        ' 2つの組み合わせで表示します
    
        Public Class Window1ViewModel
            Inherits BindableBase
    
            Private _Title As String
            Public Property Title() As String
                Get
                    Return _Title
                End Get
                Set(ByVal value As String)
                    Me.SetProperty(_Title, value)
                End Set
            End Property
    
            Public Property RequestMessage As InteractionRequest(Of ICustomConfirmation)
            Public Property RequestCommand As DelegateCommand
    
            ' コンストラクタ
            Public Sub New()
    
                Me.Title = "Prism Unity Application"
                Me.RequestMessage = New InteractionRequest(Of ICustomConfirmation)
                Me.RequestCommand = New DelegateCommand(AddressOf Me.ShowMessage)
    
            End Sub
    
            Private Sub ShowMessage()
    
                Dim message = New CustomConfirmation With {.Title = "カスタム画面の確認", .Content = "カスタム画面の確認メッセージです"}
                Me.RequestMessage.Raise(message, AddressOf Me.ShowMessageCallback)
    
            End Sub
    
            Private Sub ShowMessageCallback(message As ICustomConfirmation)
    
                If message.Confirmed AndAlso message.SelectedItem IsNot Nothing Then
                    Me.Title = $"選択した項目:{message.SelectedItem}"
                Else
                    Me.Title = "キャンセルボタンを押したか、未選択です"
                End If
    
            End Sub
    
        End Class
    
    End Namespace
    

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

  • <UserControl x:Class="Views.CustomView"
                 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"
                 xmlns:prism="http://prismlibrary.com/"
                 prism:ViewModelLocator.AutoWireViewModel="True"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300" Width="400">
    
        <StackPanel>
    
            <TextBlock Text="1つ選んでください:" />
            <ListBox 
                ItemsSource="{Binding Notification.Items}" 
                SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                SelectionMode="Single" />
    
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
    
                <Button
                    Grid.Column="0" 
                    Content="選択" 
                    Command="{Binding SelectedItemCommand}" />
    
                <Button
                    Grid.Column="1" 
                    Content="キャンセル" 
                    Command="{Binding CancelCommand}" />
    
            </Grid>
    
        </StackPanel>
        
    </UserControl>
    

  •  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="{Binding Title}" Height="350" Width="525">
    
        <!-- 要求を受けて、通知メッセージを表示する。モーダル形式の表示方法で、親画面の中央に表示する -->
        <i:Interaction.Triggers>
    
            <prism:InteractionRequestTrigger SourceObject="{Binding RequestMessage}">
                <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                    <prism:PopupWindowAction.WindowContent>
                        <local:CustomView />
                    </prism:PopupWindowAction.WindowContent>
                </prism:PopupWindowAction>
            </prism:InteractionRequestTrigger>
    
        </i:Interaction.Triggers>
    
        <!-- 画面 -->
        <StackPanel>
    
            <Button Content="button1" Command="{Binding RequestCommand}" />
            <TextBlock Text="{Binding Title}" />
    
        </StackPanel>
    
    </Window>
    

  •  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
    
    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