Busy Indicator : How update progressbar and text

Mar 7, 2012 at 1:35 PM

Hello,

I would like display BusyIndicator and I want define a value et change the text in caption...

When I display a BusyIndicator, I launch a program that modify a control Treeview...

I try with Dispatcher and BackgroundWorker, but no work !!!!

Have you a sample projet in VB.Net 2010 ?

Thank you

Coordinator
Mar 8, 2012 at 5:25 PM

Here is a small sample I made up quickly to show you how you may update the text and the progress bar value in the BusyIndicator from a background thread.  It may give you some ideas about how you are going to solve your issue.

 

XAML:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:tk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
    Title="MainWindow" Height="350" Width="525"
    x:Name="mainWindow">
   <Window.Resources>
      <Style x:Key="busyProgressBarStyle"
             TargetType="ProgressBar">
         <Setter Property="IsIndeterminate" Value="False" />
         <Setter Property="Minimum" Value="0" />
         <Setter Property="Maximum" Value="10" />
         <Setter Property="Height" Value="16" />
         <Setter Property="Value" Value="{Binding ElementName=mainWindow, Path=BusyProgressValue}" />
      </Style>
   </Window.Resources>

   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="*" />
      </Grid.RowDefinitions>

      <Button Content="Run Task"
              Grid.Row="0"
              Click="Button_Click" />

      <tk:BusyIndicator x:Name="busyIndicator"
                        Grid.Row="1"
                        ProgressBarStyle="{StaticResource busyProgressBarStyle}" />
   </Grid>
</Window>

VB.Net code:
Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.Windows
Imports System.Windows.Threading

Class MainWindow

  Public Shared ReadOnly BusyProgressValueProperty As DependencyProperty = _
    DependencyProperty.Register("BusyProgressValue", GetType(Double), GetType(MainWindow), New PropertyMetadata(0.0))

  Public Property BusyProgressValue() As Double
    Get
      Return CType(GetValue(BusyProgressValueProperty), Double)
    End Get
    Set(ByVal value As Double)
      SetValue(BusyProgressValueProperty, value)
    End Set
  End Property

  Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    If Not busyIndicator.IsBusy Then
      Me.BusyProgressValue = 0.0
      busyIndicator.BusyContent = "Please wait..."
      busyIndicator.IsBusy = True

      m_worker = New BackgroundWorker()
      m_worker.WorkerSupportsCancellation = True
      AddHandler m_worker.DoWork, AddressOf Me.DoWork
      AddHandler m_worker.RunWorkerCompleted, AddressOf Me.OnWorkCompleted

      m_worker.RunWorkerAsync(New Tuple(Of Dispatcher, Dispatcher)(mainWindow.Dispatcher, busyIndicator.Dispatcher))
    Else
      If m_worker IsNot Nothing AndAlso m_worker.IsBusy Then
        m_worker.CancelAsync()
      End If

      busyIndicator.IsBusy = False
    End If
  End Sub

  Private Sub DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    Dim arg As Tuple(Of Dispatcher, Dispatcher) = CType(e.Argument, Tuple(Of Dispatcher, Dispatcher))
    Dim mainWindowDispatcher As Dispatcher = arg.Item1
    Dim busyIndicatorDispatcher As Dispatcher = arg.Item2

    ' This loop simulates an heavy task running in background.
    For i As Integer = 1 To 10
      If worker.CancellationPending Then
        e.Cancel = True
        Exit Sub
      End If

      Thread.Sleep(1000)

      mainWindowDispatcher.Invoke(New Action(Of Integer)(AddressOf Me.UpdateProgressBarValue), i)
      busyIndicatorDispatcher.Invoke(New Action(Of Integer)(AddressOf Me.UpdateCaption), i)
    Next

  End Sub

  Private Sub UpdateCaption(ByVal iteration As Integer)
    busyIndicator.BusyContent = String.Format("Processing... {0}/10", iteration)
  End Sub

  Private Sub UpdateProgressBarValue(ByVal iteration As Integer)
    mainWindow.BusyProgressValue = iteration
  End Sub

  Private Sub OnWorkCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)

    If Object.ReferenceEquals(m_worker, worker) Then
      m_worker.Dispose()
      m_worker = Nothing

      busyIndicator.IsBusy = False
    End If
  End Sub

  Private m_worker As BackgroundWorker
End Class

Mar 10, 2012 at 12:13 PM

Hello Nebuleux,

Thank you very much for your example :)

  1. I would like in my panel Busy:
    • Titre
    • SubTitle
    • Progress Bar
    • Button Cancel (For canceled the work)
  2. I have a message error in the sub "DoWork" : "Le thread appelant doit être en mode STA.....". I want to modify a control treeview.

--> How i can define "title, subtile......" in my panel Busy Indicator ?

--> How I can modify my control Treeview UI in my Backgrounder ?

Thank you for your help.

 

Mar 16, 2012 at 8:11 AM

Hello Nebuleux,

Thank you for your help, I found a solution to my problem.

It works very well... :)