Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9304

Prism.Wpf 7.2でプログレスバーのついたダイアログを作る

$
0
0

はじめに

 Prismを使ってプログレスバーの付いたダイアログを作りました。
 進捗の値0~100をダイアログに送り、100のときにダイアログを閉じることができるという仕様にしました。

prism2.gif

環境

.Net Core 3.1
Prism.Wpf 7.2.0.1422

実装

View

xaml.png

ProgressDialog.xaml
<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を制御しています。今回はできるだけダイアログを閉じられたくなかったのでWindowStyleNoneを指定しウィンドウの閉じるボタンを非表示にしています。

ViewModel

ProgressDialogViewModel
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

ProgressDialogModel
publicclassProgressDialogModel:BindableBase{privateintprogress;publicintProgress{get{returnprogress;}set{SetProperty(refprogress,value);}}publicProgressDialogModel(IEventAggregatoreventAggregator){this.Progress=0;eventAggregator.GetEvent<ProgressMessage>().Subscribe(x=>this.Progress=x);}}
ProgressMessage
publicclassProgressMessage:PubSubEvent<int>{}

 ModelではViewModelとバインドする項目としてProgressプロパティを定義しています。
 外部からの値受け取りはIEventAggregatorを介して行うものとしProgressMessageが発行されたときにProgressの値が変化するようにしています。

Module

Module1Module
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の第一引数部分には非同期処理でエラーになった際の処理を書く予定です。
 ダイアログ呼び出しはIDialogServiceShowDialogを使って定義したダイアログを呼び出しています。

おわりに

 プログレスバーの付いたダイアログを作ることができました。他の画面から呼び出せることとプログレスバーの値を処理の進み具合によって制御できることを確認できました。

・ソースコード
https://github.com/ttlatex/PrismProgressDialog


Viewing all articles
Browse latest Browse all 9304

Trending Articles