WPFでプログレスバーを使ってみる

提供: とある社畜の頭脳整理
移動先: 案内検索

WPFでプログレスバーを使ってみると、画面が更新されないで困っちゃうんだよ。どうやら、別スレッドでプログレスバーを更新しないといけないみたいなんだ。そこで、細かいことは抜きでサンプルをあげておくよ。

xaml

<Window x:Class="ProgressBarSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="124.627" Width="525" Loaded="Window_Loaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition Height="25"/>
            <RowDefinition/>
            <RowDefinition Height="25"/>
        </Grid.RowDefinitions>
        <ProgressBar
            Grid.Row="0"
            Grid.Column="0"
            Minimum="{Binding ProgressBar_Minimum}"
            Maximum="{Binding ProgressBar_Maximum}"
            Value="{Binding ProgressBar_Value}"/>
        <Label
            Grid.Row="1"
            Grid.Column="0"
            Content="{Binding Label_Content}"/>
        <Button
            Grid.Row="3"
            Content="実行"
            Click="Button_Click"
            IsEnabled="{Binding Button_IsEnabled}"/>
    </Grid>
</Window>

DataContext

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//追加
using System.ComponentModel;

namespace ProgressBarSample
{
    class MainWindowContext : INotifyPropertyChanged
    {
        private Int32 m_ProgressBar_Minimum;
        public Int32 ProgressBar_Minimum
        {
            set
            {
                this.m_ProgressBar_Minimum = value;
                this.OnPropertyChanged("ProgressBar_Minimum");
            }
            get { return this.m_ProgressBar_Minimum; }
        }

        private Int32 m_ProgressBar_Maximum;
        public Int32 ProgressBar_Maximum
        {
            set
            {
                this.m_ProgressBar_Maximum = value;
                this.OnPropertyChanged("ProgressBar_Maximum");
            }
            get { return this.m_ProgressBar_Maximum; }
        }

        private Int32 m_ProgressBar_Value;
        public Int32 ProgressBar_Value
        {
            set
            {
                this.m_ProgressBar_Value = value;
                this.OnPropertyChanged("ProgressBar_Value");
            }
            get { return this.m_ProgressBar_Value; }
        }

        private Boolean m_Button_IsEnabled;
        public Boolean Button_IsEnabled
        {
            set
            {
                this.m_Button_IsEnabled = value;
                this.OnPropertyChanged("Button_IsEnabled");
            }
            get { return this.m_Button_IsEnabled; }
        }

        private String m_Label_Content;
        public String Label_Content
        {
            set
            {
                this.m_Label_Content = value;
                this.OnPropertyChanged("Label_Content");
            }
            get { return this.m_Label_Content; }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(String p_PropertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(p_PropertyName));
            }
        }
    }
}

ソース

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

//追加
using System.ComponentModel;
using System.Threading;
using System.Windows.Threading;

namespace ProgressBarSample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainWindowContext m_MainWindowContext;
        private BackgroundWorker m_BackgroundWorker;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.m_MainWindowContext = new MainWindowContext();
            this.DataContext = this.m_MainWindowContext;
            this.m_MainWindowContext.ProgressBar_Minimum = 0;
            this.m_MainWindowContext.ProgressBar_Maximum = 60;
            this.m_MainWindowContext.ProgressBar_Value = 0;
            this.m_MainWindowContext.Button_IsEnabled = true;

            this.m_BackgroundWorker = new BackgroundWorker();
            this.m_BackgroundWorker.DoWork += new DoWorkEventHandler(BackgroundWorker_DoWork);
            this.m_BackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker_ProgressChanged);
            this.m_BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted);
            this.m_BackgroundWorker.WorkerReportsProgress = true;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.m_MainWindowContext.Label_Content = "処理をしています";
            this.m_BackgroundWorker.RunWorkerAsync();
        }

        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            this.m_MainWindowContext.Button_IsEnabled = false;
            for (Int32 i = 0; i < 60; i++)
            {
                this.m_BackgroundWorker.ReportProgress(i + 1);
                Thread.Sleep(1000);
            }
        }

        private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.m_MainWindowContext.ProgressBar_Value = e.ProgressPercentage;
            if(e.ProgressPercentage == 60)
            {
                this.m_MainWindowContext.Label_Content = "処理が完了しました!";
            }
        }

        private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            new Window1().ShowDialog();
            this.m_MainWindowContext.Button_IsEnabled = true;
            this.m_MainWindowContext.Label_Content = String.Empty;
        }
    }
}