ユーザーに待ってもらうような重い処理をしている間に、アプリケーションがフリーズせず動作していることをウィンドウとして明示的に示す。
重い処理はBackgroundWorkerインスタンスにバックグラウンド実行させる。
XAML
ProcessingSplash.xaml
<Window x:Class="hoge.ProcessingSplash"
xmlns="(略)"
xmlns:x:="(略)"
Title="ProcessingSplash"
Width="300"
Height="110"
WindowStyle="SingleBorderWindow"
WindowStartUpLocation="CenterScreen"
ResizeMode="NoResize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<ProgressBar x:Name="progressbar"
VerticalAlignMent="Center"
HorizontalAlignment="Stretch"
Height="20"
Margin="10,15,10,5"
Width=250"
IsIndeterminate="True" />
<Label x:Name="label_status"
Grid.Row="1"
HorizontalAlignment="Center"
Content="{Binding}" />
</Grid>
</Window>
実装
ProcessingSplash.xaml.cs
using System;
using System.Windows;
using System.ComponentModel;
namespace hoge
{
public partial class ProcessingSplash : Window
{
BackgroundWorker _backgroundWorker = new BackgroundWorker();
Action action;
public bool complete { get; private set; }
public bool close { get; private set; }
public ProcessingSplash(string message, Action action)
{
InitializeComponent();
this.action = action;
DataContext = message;
complete = false;
close = false;
_backgoundWorker.DoWork += _backgroundWorker_DoWork;
_backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted;
_backgroundWorker.RunWorkerAsync();
}
private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (action != null)
action.Invoke();
}
private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
//Cancelled
complete = false;
close = true;
}
else if (e.Error != null)
{
//Exception Thrown
complete = false;
close = true;
}
else
{
//Completed
complete = true;
close = true;
}
Close();
}
protected override void OnClosing(CancelEventArgs e)
{
if (!close)
e.Cancel = true;
}
}
}
ProcessingSplash.closeプロパティは、privateな変数の方が良いかもしれない。
用例
example.cs
//(略)
ProcessingSplash ps = new ProcessingSplash("Initializing", ()=>
{
//ここで重い処理を処理させる
});
//バックグラウンド処理が終わるまで表示して待つ
ps.ShowDialog();
if (ps.complete)
{
//処理が成功した
}
else
{
//処理が失敗した
}
ラムダ式のスコープ外部にある変数やメソッドの利用にあるように、ラムダ式中ではそのままスコープ外部の変数が使えるので、わざわざ変数をProcessingSplashクラスへ委譲せずに済む。