はじめに
Prismを使ってプログレスバーの付いたダイアログを作りました。
進捗の値0~100をダイアログに送り、100のときにダイアログを閉じることができるという仕様にしました。
環境
.Net Core 3.1
Prism.Wpf 7.2.0.1422
実装
View
<UserControlx:Class="Module1.Views.ProgressDialog"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Module1.Views"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"Height="100"Width="200"mc:Ignorable="d"xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True"xmlns:viewModels="clr-namespace:Module1.ViewModels"d:DataContext="{d:DesignInstance viewModels:ProgressDialogViewModel}"><prism:Dialog.WindowStyle><StyleTargetType="Window"><SetterProperty="ResizeMode"Value="NoResize"/><SetterProperty="ShowInTaskbar"Value="False"/><SetterProperty="SizeToContent"Value="WidthAndHeight"/><SetterProperty="WindowStyle"Value="None"/><SetterProperty="BorderThickness"Value="1"/></Style></prism:Dialog.WindowStyle><Grid><Grid.RowDefinitions><RowDefinitionHeight="Auto"></RowDefinition><RowDefinitionHeight="Auto"></RowDefinition></Grid.RowDefinitions><WrapPanelMargin="10,15"><LabelWidth="30"HorizontalContentAlignment="Right"Content="{Binding Progress}"/><ProgressBarHeight="15"Width="130"Value="{Binding Progress}"/></WrapPanel><ButtonGrid.Row="1"Height="20"Width="100"VerticalAlignment="Bottom"Margin="0,12"Content="閉じる"Command="{Binding CloseCommand}"/></Grid></UserControl>
ダイアログ用にプログレスバーと閉じるボタンが付いたViewを作成します。
prism:Dialog.WindowStyle
タグでダイアログとして呼び出された際のWindowStyleを制御しています。今回はできるだけダイアログを閉じられたくなかったのでWindowStyle
にNone
を指定しウィンドウの閉じるボタンを非表示にしています。
ViewModel
publicclassProgressDialogViewModel:BindableBase,IDialogAware{privateintprogress;publiceventAction<IDialogResult>RequestClose;publicintProgress{get{returnprogress;}set{SetProperty(refprogress,value);}}publicDelegateCommandCloseCommand{get;}publicstringTitle=>"Dialog1";publicProgressDialogViewModel(ProgressDialogModelmodel){this.Progress=model.Progress;model.PropertyChanged+=(_,e)=>{if(e.PropertyName=="Progress"){this.Progress=model.Progress;}};this.CloseCommand=newDelegateCommand(()=>this.CloseDialog(),()=>this.Progress>=100).ObservesProperty(()=>this.Progress);}publicboolCanCloseDialog()=>true;publicvoidOnDialogClosed()=>this.Progress=0;publicvoidOnDialogOpened(IDialogParametersparameters){}privatevoidCloseDialog()=>RequestClose?.Invoke(newDialogResult(ButtonResult.OK));}
ViewModelではViewのプログレスバーにバインドする項目としてProgress
プロパティを定義しています。
CloseCommad
ではダイアログを閉じるときの動作を担当しています。使用可否条件としてProgress
の値が100以上であることを指定しています。
ダイアログとして利用するためにIDialogAware
を実装しています。
Model
publicclassProgressDialogModel:BindableBase{privateintprogress;publicintProgress{get{returnprogress;}set{SetProperty(refprogress,value);}}publicProgressDialogModel(IEventAggregatoreventAggregator){this.Progress=0;eventAggregator.GetEvent<ProgressMessage>().Subscribe(x=>this.Progress=x);}}
publicclassProgressMessage:PubSubEvent<int>{}
ModelではViewModelとバインドする項目としてProgress
プロパティを定義しています。
外部からの値受け取りはIEventAggregator
を介して行うものとしProgressMessage
が発行されたときにProgress
の値が変化するようにしています。
Module
publicclassModule1Module:IModule{publicvoidOnInitialized(IContainerProvidercontainerProvider){_=containerProvider.Resolve<ProgressDialogModel>();}publicvoidRegisterTypes(IContainerRegistrycontainerRegistry){containerRegistry.RegisterSingleton<ProgressDialogModel>();containerRegistry.RegisterDialog<ProgressDialog>();}}
Moduleでは他のプロジェクトでダイアログを利用できるようDIコンテナにViewとModelを登録しています。ModelはシングルトンとしてDIコンテナに登録しました。
ダイアログ呼び出し部分
publicDelegateCommandShowDialogCommand{get;}publicMainWindowViewModel(IDialogServicedialogService,IEventAggregatoreventAggregator){this.ShowDialogCommand=newDelegateCommand(()=>{_=Task.Run(async()=>{eventAggregator.GetEvent<ProgressMessage>().Publish(0);awaitTask.Delay(1000);eventAggregator.GetEvent<ProgressMessage>().Publish(33);awaitTask.Delay(1000);eventAggregator.GetEvent<ProgressMessage>().Publish(66);awaitTask.Delay(1000);eventAggregator.GetEvent<ProgressMessage>().Publish(100);}).ContinueWith(x=>x.Exception/* エラー処理 */,TaskContinuationOptions.OnlyOnFaulted);dialogService.ShowDialog(nameof(ProgressDialog),newDialogParameters(),null);});}
ダイアログのプロジェクトとは別の画面を作り、そのViewModelにShowDialogCommand
というダイアログの動作確認をするためのコマンドを用意しました。
ShowDialogCommand
では、非同期処理呼び出しとダイアログ呼び出しの2つを実行しています。
非同期処理では処理中にIEventAggregator
を介してProgressMessage
を発行しModelに進捗を表す数値を送っています。ここでは1秒間隔でModelの進捗の値を変更しています。ContinueWith
の第一引数部分には非同期処理でエラーになった際の処理を書く予定です。
ダイアログ呼び出しはIDialogService
のShowDialog
を使って定義したダイアログを呼び出しています。
おわりに
プログレスバーの付いたダイアログを作ることができました。他の画面から呼び出せることとプログレスバーの値を処理の進み具合によって制御できることを確認できました。