週末副業記

土日は副業エンジニアのブログです。副業に関することを投稿します。

【WPF】進捗インジケータのサンプル【C#】【XAML】


f:id:aisakakun:20200802001009p:plain
進捗状況・プログレスバーなどで検索するも、思ったように出てこなかったので作成しました。※結論、最適な検索キーワードは「進捗インジケータ」「プログレストラッカー」のようです。進捗状況をプログレスバーで表すには適していない場合があります。例えば単純に何秒間かユーザーに待たせるような場合は、進捗しているわけではないためプログレスバー以外の手段を用いた方がよいと思います。

機能概要

ボタンをクリックすると、正方形を正方形上に配置することにより構成された進捗インジケータが動作を行います。

完成イメージ

f:id:aisakakun:20200802002040p:plain
完成イメージ

画面更新部

進捗状況をあらわすようにプログラムをC#で書いた場合でも画面を更新しなければ、それがGUIに反映されることはありません。そのため、必ず下記を加える必要があります。

private void DoEvents()
{
      DispatcherFrame frame = new DispatcherFrame();
      var callback = new DispatcherOperationCallback(ExitFrames);
      Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, callback, frame);
      Dispatcher.PushFrame(frame);
}

private object ExitFrames(object obj)
{
     ((DispatcherFrame)obj).Continue = false;
     return null;
} 

進捗インジケータ更新部

12個の正方形で構成されています。

private void ProgressAnimation(int time)//timeの範囲:0<=time<=11
{
      int arrayNum = time;
      int arrayNum1 = time - 1 >= 0 ? time - 1 : time - 1 + 12;
      int arrayNum2 = time - 2 >= 0 ? time - 2 : time - 2 + 12;
      rectProgressArray[arrayNum].Fill = progressColor0;
      rectProgressArray[arrayNum1].Fill = progressColor1;
      rectProgressArray[arrayNum2].Fill = progressColor2;
      for (int i = 0; i < 12; i++)
      {
           if (arrayNum != i && arrayNum1 != i && arrayNum2 != i)
           {
                rectProgressArray[i].Fill = progressColor3;
            }
       }
}

コード全文

ベタうちで書いていますので、リファクタリングして活用ください。

C#のコード部(MainWindow.xaml.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
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.Windows.Threading;

namespace WpfApp5
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {

        private static Rectangle[] rectProgressArray = new Rectangle[12];
        private static SolidColorBrush progressColor0 = new SolidColorBrush();
        private static SolidColorBrush progressColor1 = new SolidColorBrush();
        private static SolidColorBrush progressColor2 = new SolidColorBrush();
        private static SolidColorBrush progressColor3 = new SolidColorBrush();

        public MainWindow()
        {
            InitializeComponent();
            InitialRect();
        }

        private void InitialRect()
        {
            rectProgressArray[0] = rectProgress0;
            rectProgressArray[1] = rectProgress1;
            rectProgressArray[2] = rectProgress2;
            rectProgressArray[3] = rectProgress3;
            rectProgressArray[4] = rectProgress4;
            rectProgressArray[5] = rectProgress5;
            rectProgressArray[6] = rectProgress6;
            rectProgressArray[7] = rectProgress7;
            rectProgressArray[8] = rectProgress8;
            rectProgressArray[9] = rectProgress9;
            rectProgressArray[10] = rectProgress10;
            rectProgressArray[11] = rectProgress11;

            progressColor0.Color = Color.FromRgb(0, 128, 255);
            progressColor1.Color = Color.FromRgb(155, 205, 255);
            progressColor2.Color = Color.FromRgb(244, 249, 255);
            progressColor3.Color = Color.FromRgb(255, 255, 255);
        }
        //画面更新部
        private void DoEvents()
        {
            DispatcherFrame frame = new DispatcherFrame();
            var callback = new DispatcherOperationCallback(ExitFrames);
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, callback, frame);
            Dispatcher.PushFrame(frame);
        }

        private object ExitFrames(object obj)
        {
            ((DispatcherFrame)obj).Continue = false;
            return null;
        } 
  //画面更新部

        //進捗インジケータ更新部
        private void ProgressAnimation(int time)//timeの範囲:0<=time<=11
        {
            int arrayNum = time;
            int arrayNum1 = time - 1 >= 0 ? time - 1 : time - 1 + 12;
            int arrayNum2 = time - 2 >= 0 ? time - 2 : time - 2 + 12;
            rectProgressArray[arrayNum].Fill = progressColor0;
            rectProgressArray[arrayNum1].Fill = progressColor1;
            rectProgressArray[arrayNum2].Fill = progressColor2;
            for (int i = 0; i < 12; i++)
            {
                if (arrayNum != i && arrayNum1 != i && arrayNum2 != i)
                {
                    rectProgressArray[i].Fill = progressColor3;
                }
            }
        }
       //進捗インジケータ更新部

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            int count = 0;

            while (true)
            {
                count++;
                Thread.Sleep(100);//早すぎるのでスリープ
                if (count == 12)
                {
                    count = 0;
                }
                ProgressAnimation(count);
                DoEvents();//画面を更新する
            }
        }
    }
}

xamlのコード部(MainWindow.xaml)

~部を下記に書き換えてご使用ください。

    <Grid Margin="0,0,528.333,366.667">
        <Canvas Grid.Row="0" Grid.ColumnSpan="2" Margin="0,0,40,0">
            <Rectangle Name ="rectProgress0"  Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6" StrokeThickness="0.5" Canvas.Left="124" Canvas.Top="16"/>
            <Rectangle Name ="rectProgress1" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="132" Canvas.Top="16"/>
            <Rectangle Name ="rectProgress2" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="140" Canvas.Top="16"/>
            <Rectangle Name ="rectProgress3" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6" StrokeThickness="0.5" Canvas.Left="148" Canvas.Top="16"/>
            <Rectangle Name ="rectProgress11" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="124" Canvas.Top="24"/>
            <Rectangle Name ="rectProgress10" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6" StrokeThickness="0.5" Canvas.Left="124" Canvas.Top="32"/>
            <Rectangle Name ="rectProgress9" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="124" Canvas.Top="40"/>
            <Rectangle Name ="rectProgress8" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="132" Canvas.Top="40"/>
            <Rectangle Name ="rectProgress7" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="140" Canvas.Top="40"/>
            <Rectangle Name ="rectProgress6" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="148" Canvas.Top="40"/>
            <Rectangle Name ="rectProgress5" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="148" Canvas.Top="32"/>
            <Rectangle  Name ="rectProgress4" Fill="White" HorizontalAlignment="Left" Height="6" Stroke="#FFA6A7AB" VerticalAlignment="Top" Width="6"  StrokeThickness="0.5" Canvas.Left="148" Canvas.Top="24"/>
        </Canvas>
        <Button Content="Button" HorizontalAlignment="Left" Height="22" Margin="33,17,-106,-39" VerticalAlignment="Top" Width="73" Click="Button_Click" Background="#FF6E71D1" Foreground="White"/>
    </Grid>