LoginSignup
20
21

More than 5 years have passed since last update.

重い処理の実行中にプログレスバー{IsIndeterminate=True}付きウィンドウを表示する

Last updated at Posted at 2012-04-16

ユーザーに待ってもらうような重い処理をしている間に、アプリケーションがフリーズせず動作していることをウィンドウとして明示的に示す。
重い処理は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クラスへ委譲せずに済む。

20
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
21