【WPF】ProgressRingを使って時間のかかる処理を分かりやすくする

公開日:2019-06-24
最終更新:2019-06-24
※この記事は外部サイト(https://www.doraxdora.com/blog/2017/07/28/...)からのクロス投稿です

WEBなんかでよく見かける、処理中にローディング画像を表示するってのをやってみます。

重い処理なんかで、ローディング表示がない場合はユーザーが動いているのかどうか心配になり、挙句の果てに強制終了してしまったりしますので、大事ですよね。
体感速度も違ってきますし。

プログラムは前回のものを利用します。
【WPF】MahApps.Metro で見た目をスタイリッシュにしてみる

スタイルの追加

StyleDic.xaml

宣言の追加

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
                    xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"  
                    xmlns:local="clr-namespace:WpfApp1.Style">  

スタイルの追加

    <!-- プログレスリング -->  
    <Style x:Key="pgr-normal" TargetType="{x:Type Mah:ProgressRing}" >  
        <Setter Property="Foreground" Value="#33adff" />  
        <Setter Property="IsActive" Value="False" />  
        <Setter Property="Width" Value="100" />  
        <Setter Property="Height" Value="100" />  
        <Setter Property="Panel.ZIndex" Value="100" />  
    </Style>  
    <!-- プログレスオーバーレイ-->  
    <Style x:Key="rec-overlay" TargetType="{x:Type Rectangle}" >  
        <Setter Property="Fill" Value="#000000" />  
        <Setter Property="Opacity" Value="0.2" />  
        <Setter Property="Panel.ZIndex" Value="1000" />  
        <Setter Property="Margin" Value="0,0,0,30" />  
        <Setter Property="Visibility" Value="Collapsed" />  
    </Style>  

画面の修正

MainWindow.xaml

抜粋

<!-- Gridの高さと幅を設定 -->  
<Grid Height="350" Width="530">  

<!-- プログレスリングとオーバーレイを追加 -->  
        <Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />  
        <Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>  

全体

<Mah:MetroWindow x:Class="WpfApp1.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        xmlns:local="clr-namespace:WpfApp1"  
        xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"  
        mc:Ignorable="d"  
        Title="一覧" Height="350" Width="530"  
        GlowBrush="{DynamicResource AccentColorBrush}"  
        BorderThickness="1"  
        >  
    <Window.Resources>  
        <ResourceDictionary Source="/Style/StyleDic.xaml"/>  
    </Window.Resources>  

    <Grid Height="350" Width="530">  
        <Grid.Resources>  
            <local:KindConverter x:Key="KindConv"/>  
        </Grid.Resources>  
        <Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />  
        <Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>  

        <Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}"/>  
        <TextBox x:Name="search_name" Margin="56,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"  Style="{StaticResource MetroTextBox}"/>  
        <Label Content="種別:" Margin="201,10,0,0" Style="{StaticResource lb-normal}"/>  
        <ComboBox x:Name="search_kind" Margin="252,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="125"  Style="{StaticResource MetroComboBox}"/>  
        <Button x:Name="search_button" Content="検索" HorizontalAlignment="Left" Margin="432,12,0,0" VerticalAlignment="Top" Width="75"  Click="search_button_Click" Style="{DynamicResource SquareButtonStyle}"/>  

        <DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,43,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >  
            <DataGrid.Columns>  
                <DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="50"/>  
                <DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="True" Width="100"/>  
                <DataGridTextColumn Binding="{Binding Sex}" ClipboardContentBinding="{x:Null}" Header="性別" IsReadOnly="True" Width="40"/>  
                <DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="True" Width="40"/>  
                <DataGridTextColumn Binding="{Binding Kind, Converter={StaticResource KindConv}}" ClipboardContentBinding="{x:Null}" Header="種別" IsReadOnly="True" Width="120"/>  
                <DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="True" Width="*"/>  
            </DataGrid.Columns>  
        </DataGrid>  
        <Button x:Name="add_button" Content="追加" HorizontalAlignment="Left" Margin="10,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="add_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="upd_button" Content="更新" HorizontalAlignment="Left" Margin="90,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="upd_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="del_button" Content="削除" HorizontalAlignment="Left" Margin="170,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="del_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="imp_button" Content="CSV読込" HorizontalAlignment="Left" Margin="250,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="imp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="exp_button" Content="CSV出力" HorizontalAlignment="Left" Margin="330,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="exp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="fld_button" Content="フォルダ参照" HorizontalAlignment="Left" Margin="410,273,0,0" VerticalAlignment="Top" Width="97" Height="30" Click="fld_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
    </Grid>  
</Mah:MetroWindow>  

プログラムの修正

ライブラリ使用宣言の追加

MainWindow.xaml.cs

抜粋

using System.ComponentModel;  

検索処理の修正

検索処理を、BackgroundWorkerを使って非同期処理として分離します。

MainWindow.xaml.cs

        /// <summary>  
        /// 検索処理(非同期)  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e"></param>  
        private void SearchProcess(object sender, DoWorkEventArgs e)  
        {  
            // 時間のかかるようにする  
            System.Threading.Thread.Sleep(3000);  

            using (var conn = new MySqlConnection("Database=DB01;Data Source=localhost;User Id=USER01;Password=USER01; sqlservermode=True;"))  
            {  
                conn.Open();  

                // 猫データマスタを取得してコンボボックスに設定する  
                using (DataContext con = new DataContext(conn))  
                {  
                    String searchName = (e.Argument as Object[])[0] as String;  
                    String searchKind = (e.Argument as Object[])[1] as String;  

                    // データを取得  
                    Table<Cat> tblCat = con.GetTable<Cat>();  

                    // サンプルなので適当に組み立てる  
                    IQueryable<Cat> result;  
                    if (searchKind == "")  
                    {  
                        // 名前は前方一致のため常に条件していしても問題なし  
                        result = from x in tblCat  
                                 where x.Name.StartsWith(searchName)  
                                 orderby x.No  
                                 select x;  
                    }  
                    else  
                    {  
                        result = from x in tblCat  
                                 where x.Name.StartsWith(searchName) &amp; x.Kind == searchKind  
                                 orderby x.No  
                                 select x;  

                    }  
                    e.Result = result.ToList();  
                }  

                conn.Close();  
            }  
        }  

        /// <summary>  
        /// 検索完了処理(非同期)  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e"></param>  
        private void SearchProcessCompleted(object sender, RunWorkerCompletedEventArgs e)  
        {  
            this.dataGrid.ItemsSource = e.Result as List<Cat>;  
            ToggleProgressRing();  
        }  

        /// <summary>  
        /// 処理中イメージの表示/非表示切り替え  
        ///   
        /// </summary>  
        private void ToggleProgressRing()  
        {  
            if (this.loading_image.IsActive)  
            {  
                this.loading_image.IsActive = false;  
                this.rec_overlay.Visibility = Visibility.Collapsed;  
            }  
            else  
            {  
                this.loading_image.IsActive = true;  
                this.rec_overlay.Visibility = Visibility.Visible;  
            }  
        }  

メソッドの修正

検索ボタンをクリックした際に、先ほど追加した非同期処理を呼び出すように修正します。

        /// <summary>  
        /// 検索ボタンクリックイベント.  
        ///   
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e"></param>  
        private void search_button_Click(object sender, RoutedEventArgs e)  
        {  
            logger.Info("検索ボタンクリック");  

            Object[] param = new Object[2];  
            param[0] = this.search_name.Text;  
            param[1] = (this.search_kind.SelectedValue as Kind).KindCd;  

            BackgroundWorker worker = new BackgroundWorker();  
            worker.DoWork += SearchProcess;  
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SearchProcessCompleted);  
            worker.RunWorkerAsync(param);  

            ToggleProgressRing();  

        }  

起動してみる

動画
https://www.youtube.com/embed/MOaQGtqEoUA

いい感じですね。

ローディング表示だけだと、処理中にボタンなんかが押せてしまうので図形をかぶせるようにしてみました。

まとめ

簡単な(画面の少ない)アプリであればこんな方法でも十分かなと思います。

ソースはこちら

GitHub

ではでは。

記事が少しでもいいなと思ったらクラップを送ってみよう!
18
+1
@doraxdoraの技術ブログ 主に Java, C#, Python, Javascript の記事を載せていく予定。

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする