[WPF] プログレスバーの使い方まとめ

[WPF] プログレスバーの使い方まとめ

WPF でプログレスバーを使う

アプリ内で時間のかかる処理を行う場合、プログレスバーを画面に表示することでユーザーはその進捗を直感的、視覚的に把握できるようになります。

何の表示もないまま時間のかかる処理を実行すると、画面が固まっているように見えてユーザーを不安にさせてしまいます。したがって重たい処理を行う時はプログレスバーなどで進捗を示してあげましょう。

WPFには標準のコントロールとして、ProgressBar が提供されています。ここではこのコントロールの使い方を見ていきます。

未定プログレスバー(マーキースタイル)

実行するタスクの処理量や時間が予測できないような場合(タスクの進行割合を数値で示せない場合)は、未定プログレスバーを使います。Windows だと マーキースタイルと呼ばれるようです。

上の画像のように、一定幅のバー内を繰り返し動くようなアニメーションのプログレスバーになります。これはタスクが現在進行形で処理中ということを意味します。

サンプルコード

xaml

<ProgressBar 
    HorizontalAlignment="Center"  
    VerticalAlignment="Center" 
    Width="200" 
    Height="20"
    IsIndeterminate="True" />

最終行で指定している IsIndeterminate プロパティを True にすることで繰り返しのアニメーションが表示されるようになります。

処理開始時にこのプログレスバーを表示し、時間のかかる処理が完了したらプログレスバーごと Visibility を変更して消すというような使い方をします。

進捗度を示すプログレスバー

ProgressBar のプロパティ Value に現在の進捗度を数値で設定することで、バーの緑色の部分の幅を変更できます。ここに進捗度をバインドしてやれば、進捗度に従ってアニメーションして見えるようになります。

こんな感じで進捗度に従ってバーの緑色が動きます。

サンプルコード

上で示した画像のように、ボタンを押したらタスクの処理を実行し、その進捗をプログレスバーに表示するようにします。

xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="300">
    <StackPanel 
        HorizontalAlignment="Center" 
        VerticalAlignment="Center">

        <!-- プログレスバー -->
        <ProgressBar 
            Width="200" 
            Height="20"
            Minimum="0"
            Maximum="100"
            Value="{Binding Progress}"
            />
        <Button Content="実行" Width="75" Margin="10" Click="Button_Click"/>

    </StackPanel>
</Window>

ProgressBar の Minimum, MaximumValue がとりうる値の範囲(最小値と最大値)を設定します。ここでは 0~100 までの範囲としています。

Value は進捗度を表す数値を設定します。ここではバインドしています。

サンプルなので、ほかのコードはすべてコードビハインドに書きます。

ではボタンクリック時のイベントを定義していきましょう。

xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }

    // 実行ボタン押下時のイベント
    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        var vm = this.DataContext as ViewModel;

        await Task.Run(async () =>
        {
            while(vm.Progress < 100)
            {
                vm.Progress += 1;
                await Task.Delay(10);
            }
        });

        MessageBox.Show("タスクが完了しました。");
        vm.Progress = 0;
    }
}

// 進捗を表すための ViewModel
public class ViewModel : INotifyPropertyChanged
{
    private int _Progress;
    public int Progress
    {
        get { return this._Progress; }
        set
        {
            this._Progress = value;
            this.NotifyProperyChanged(nameof(this.Progress));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyProperyChanged(string name)
    {
        this.PropertyChanged?.Invoke(
            this,
            new PropertyChangedEventArgs(name)
        );
    }
}

ViewModel は単純に変更通知機能を実装した整数型のプロパティ Progress を持つだけの単純なクラスです。

実際の重たい処理にあたる部分は以下の箇所です。

await Task.Run(async () =>
{
    while(vm.Progress < 100)
    {
        vm.Progress += 1;
        await Task.Delay(10);
    }
});

このコードは非同期で進捗度を100までカウントアップしています。1カウントするごとに 0.01秒のディレイを挟んでいます。

こうするることで Progress がカウントアップされるたびに、画面の ProgressBar の緑色の部分が更新されるようになります。

このタスクが完了するまで await するようにしており、進捗が100になるとメッセージボックスを表示しています。

もう一度動きを見てみましょう。

いい感じに動いていますね。実はこのままだと実行ボタンを何度も押せてしまうので、実運用にはもう少し制御が必要ですが、基本はこのようにして使います。

以上。

.NET Frameworkカテゴリの最新記事