2020年5月4日月曜日

VB WPF お勉強 14 ProgressBar 簡単な例

ProgressBar ... はい、見ている分には 便利なんですが ... 。
コードを書くのを躊躇して仕舞います。
少し、面倒なのでしたね。
自分としては、余り、出番が無いので、備忘録的に。  ;)


先ずは、お断りして置きます。
これから書く事は、素人の 悪足掻き! です。
レベルは低いので、そのお心算で、ご覧下さい。

ProgressBar 。

進捗状況を明示する コントロール ですね。

私、余り、使いません ... 。
だって、コードを書くのが簡単では無いから ... 。  X|

通常、Wait Cursor で お茶を濁しています。
今は作業実行中ですよ! と、ね。

でも、今回、WPF & .mdf (LocalDB) を使ったもので、
待っていて不安になるケースがありました。

データ自動取得で、ファイル群 や DB を操作するのですが、
ただ、カーソルがくるくる回っているのを眺めていて、不安が過ったのです。
一体、どれくらいの時間が掛かるのか ... ?。

事後に、
それは、LocalDB が Stopped していて、再度 Session を開くのに、
大半の時間を費やしていたのだろうと、分かったのですが、
最初は、
対象ファイルを全て舐めて行く必要がある為に、
単に、数多のファイルを相手に、奮闘しているのだろうと、想像し、
進捗状況を提示する必要があると感じたのです。

進捗状況 なら ProgressBar の出番!です。

でも、これって、割と面倒なコードが必要です。

UI 処理 と 実処理 とを 分けないといけないからですね。



以下に、稚拙なコードを載せます。
実際には、DB と DataGrid なのですが、
オマケに、DB 上の有無確認と タグ取得と が必要なので 結構 複雑なのですが、
端折って、ListBox と Sleep で代用(単純化)します。


ListBox と Button とを画面左右に各1個配置し、右のみ ProgressBar も配置します。
左は普通に ListBox Items を加えるロジック、
これに対し、右は、
そのコードから ProgressBar に進捗を表示するロジックに変えたケースです。


Async を使った Button Click Handler と、
それを受ける Await Task.Run(Function() DoWork()) の DoWork Routine(Function) と
進捗状況を渡す ShowProgress の Routine(Sub) と、
から構成されますね。
良く例示されるコードは 中断 を含むものですが、
今回は DB 登録ですから、中断はさせません。 (可能ですが、余り、意味が無い ... ?)
ですから、 ProgressBar のサンプルとしてはシンプルだと思います。

先ずは、こんなコード(画面左用)からスタートしたとします。
    Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click
        Dim files As New List(Of String)
        For i As Integer = 1 To 20
            files.Add((11111 * i).ToString & ".wma")
        Next
        Mouse.OverrideCursor = Cursors.Wait
        For Each item In files
            'Handling File's Metadata
            '
            Me.ListBox1.Items.Add(item)
            ' Sleeping As Hard Works
            Threading.Thread.Sleep(500)
        Next
        Mouse.OverrideCursor = Nothing
        MessageBox.Show("End Of Work        >  " & files.Count.ToString & " Files",
                        Me.Title)
    End Sub

このコードから ProgressBar を活かす画面右用を。

Class MainWindow

    Private files2 As New List(Of String)

    ' 中略 (Omission : Private Sub Button1_Click)

    Private Async Sub Button2_Click(sender As Object, e As RoutedEventArgs) Handles Button2.Click
        'Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click

        Dim files As New List(Of String)
        For i As Integer = 1 To 20
            files.Add((11111 * i).ToString & ".wma")
        Next
        Mouse.OverrideCursor = Cursors.Wait

        ' このブロックを外に出す (Take This Block Out As 'DoWork')
        'For Each item In files
        '    Me.ListBox1.Items.Add(item)
        '    ' Sleeping As Hard Works
        '    Threading.Thread.Sleep(500)
        'Next
        ' このブロックを外に出す (Take This Block Out ; End)

        ' ProgressBar Start
        Me.ProgressBar2.Minimum = 0.0                       'ProgressBar
        Me.ProgressBar2.Maximum = 100.0                     'ProgressBar
        Dim p1 = New Progress(Of Integer)(AddressOf ShowProgress)
        Dim result1 As String = Await Task.Run(Function() DoWork(p1, files))  'DoWork

        For Each item2 In files2
            Me.ListBox2.Items.Add(item2)
        Next
        ' ProgressBar End

        Mouse.OverrideCursor = Nothing

        MessageBox.Show("End Of Work        >  " & files.Count.ToString & " Files",
                        Me.Title)
        'End Sub
    End Sub

    Private Sub ShowProgress(percent As Double)
        Me.ProgressBar2.Value = percent
    End Sub

    Private Function DoWork(progress As IProgress(Of Integer), ByRef files As List(Of String))
        Dim i As Integer = 1

        For Each item In files

            'Handling File's Metadata
            '
            'Me.ListBox1.Items.Add(item)    ' Never Touch UI Element!!! > files2 As New Field Variable
            files2.Add(item)

            ' Sleeping As Hard Works
            Threading.Thread.Sleep(500)

            'Report Progress
            progress.Report(i / files.Count * 100.0)

            i += 1
        Next
        Return "Done"
    End Function
End Class


これを実行すると、右の方が遅い気がしますね。  下図参照 Debug Mode 。
ProgressBar の表示をする分、負荷が掛かっているのでしょうが、
見ていれば、多少遅くても、進捗状況を把握出来るので、安心感はあるのではないでしょうか?。



それにしても、 ProgressBar は ... 難しい ... 。



0 件のコメント:

コメントを投稿