記事概要
UWPにおいて、時間のかかる処理開始後、プログレスリング(「処理中ですよ」を表す、くるくる回るアニメーション)をダイアログとして既存の画面の上に重ねて表示し、処理完了後には自動で閉じさせる方法について。
※ダイアログとは:
ダイアログ コントロール | Microsoft Docs
※プログレスリングとは:
プログレス コントロールのガイドライン | Microsoft Docs
実現したいこと概要
まず、実現したいことに関する処理の流れについてです。
① データの登録ボタンクリック
② データの登録処理が開始される
③ 画面上に、処理中ダイアログ(ダイアログ上にプログレスリングも表示させる)が表示される
④ データの登録処理が進む
⑤ データの登録処理が完了する
⑥ 処理中ダイアログを(ユーザー操作ではなく)コードから閉じる
という流れを考えています。
実現方法の流れ
まず、ダイアログとして表示させる用のXAMLを用意します。
続いて、実際の画面用のXAMLをいじります。
最後に、コードビハインドをいじります。
1.ダイアログとして表示させる用のXAMLを用意する
(1) ソリューションエクスプローラーにおいて、どこか適当な場所で右クリックをします。
(2) 追加>新しい項目の追加>VisualC#>コンテンツダイアログ を選んで、xamlファイルを作成します。
今回仮名称として「RegisterProgressDialog」という名前にしました。
(3) 作成したファイルを編集します。
以下のような感じで作成しました。
<ContentDialog x:Class="XXXXX.RegisterProgressDialog" 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" Title="処理中ですよ" mc:Ignorable="d"> <Grid> <ProgressRing Width="50" Height="50" HorizontalAlignment="Center" IsActive="True" /> </Grid> </ContentDialog>
ユーザーにダイアログのボタン操作はさせないので、デフォルトで用意してある
IsPrimaryButtonEnabled="True" IsSecondaryButtonEnabled="True" PrimaryButtonText="OK" SecondaryButtonText="Cancel"
のプロパティについては削除しています。
2.実際の画面用のXAMLをいじる
ButtonのClickアクションとしてコードビハインドにおいて、データ登録用メソッド(仮称として"RegisterData"メソッドとしておきます)を設定しておきます。
<Button Click="{x:Bind 【RegisterDataメソッド】}" Content="登録"/>
※環境によってメソッドの指定方法も異なると思うので、【】内は適宜変えてください
3.コードビハインドをいじる
3-1.ダイアログを表示させる処理の記述
RegisterDataメソッド内において、処理の先頭に
var progressDialog = new RegisterProgressDialog(); var showingDialog = progressDialog.ShowAsync();
を書きます。
1行目では、先ほど2で作成したダイアログXAMLを読み込んでいます。
2行目では、1行目で読み込んだダイアログを実際のUWPの画面に表示させます。
ここでawait progressDialog.ShowAsync();
としていないのは、そうやって書いてしまうと画面の操作を待ち続けて先に進まなくなってしまうからです。
3-2. データ登録メソッドの記述
そのあとは、データ登録メソッドを記述します。
ここのソースコードは割愛します。
3-3. ダイアログを閉じる処理の記述
RegisterDataメソッドの末尾に、以下を記述します。
showingDialog.Cancel(); progressDialog.Hide();
1行目では、ダイアログの待機処理を終了させます。(僕の試した限りでは、これを書かなくても問題なく動作したので、なぜ必要なのかがよくわかっておりません…。)
2行目では、ダイアログを閉じます。
これで実際に動かしてみれば、想定通り処理開始→プログレスリングが画面上に表示→処理終了後、プログレスリングが消える となっているはずです。
補足
なんだかまどろっこしい書き方をしているのかもしれませんが、ちょっと以下のような理由がありこういう書き方になっています。
・MVVMモデルにあこがれており、XAMLのコードビハインドを、XAML付属のCSファイルではなく、別のファイルに分けていたため、その別ファイル内において、this.【ダイアログ】.ShowAsync() に該当する処理を書く方法がよくわからなかった
・ProgressRingをダイアログに追加する方法として、XAMLで記述する方法しかわからなかった(CSファイル上でProgressRingをContentDialog上に載せる方法がわからなかった)
参考サイト
How to make a modal progress dialog in Windows 10 UWP - Edi.Wang
僕は中国語はさっぱりなので、Google翻訳で翻訳して参考にさせていただきました。UWPのPopup/Flyout/Dialog系のコントロール - SourceChord
「ContentDialog」の「別のXAMLファイル上に定義」という部分について参考にさせていただきました。ほかの部分もシンプルにまとまっており、わかりやすかったです。