ProgressBar on BusyIndicator doesn't update when value changes
-
Friday, May 20, 2011 1:19 PM
I have a BusyIndicator and I want to display a progress bar on it.
Apparently although the default style of the BusyIndicator has a progress bar on it, you can't set its value so you have to add your own using BusyContentTemplate.
Having done so, once again there doesn't seem to be any way to directly access the Value property of the ProgressBar, so you have to use a Binding.
I have created a class to bind the ProgressBar to so that I can set its Value and Maximum, but the Value doesn't update on screen even though I've implemented INotifyPropertyChanged on my class.
Here is my XAML:
<toolkit:BusyIndicator Name="busy" BusyContent="{Binding}"><toolkit:BusyIndicator.BusyContentTemplate><DataTemplate><StackPanel><TextBlock Text="Uploading..." HorizontalAlignment="Center" /><ProgressBar Value="{Binding value}" Maximum="{Binding maximum}" Height="15" /></StackPanel></DataTemplate></toolkit:BusyIndicator.BusyContentTemplate><!-- Remove unnecessary default ProgressBar --><toolkit:BusyIndicator.ProgressBarStyle><Style TargetType="ProgressBar"><Setter Property="Visibility" Value="Collapsed" /></Style></toolkit:BusyIndicator.ProgressBarStyle><Grid Name="grdPage"><toolkit:BusyIndicator Name="busy" BusyContent="{Binding}"> <toolkit:BusyIndicator.BusyContentTemplate> <DataTemplate> <StackPanel> <TextBlock Text="Uploading..." HorizontalAlignment="Center" /> <ProgressBar Value="{Binding value}" Maximum="{Binding maximum}" Height="15" /> </StackPanel> </DataTemplate> </toolkit:BusyIndicator.BusyContentTemplate> <!-- Remove unnecessary default ProgressBar --> <toolkit:BusyIndicator.ProgressBarStyle> <Style TargetType="ProgressBar"> <Setter Property="Visibility" Value="Collapsed" /> </Style> </toolkit:BusyIndicator.ProgressBarStyle> <Grid Name="grdPage"> <!-- Page contents in here --> </Grid> </toolkit:BusyIndicator>And my code:Public Class ProgressUpdater Implements INotifyPropertyChanged Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Private pVal As Integer, pMax As Integer Public Property value As Integer Get Return pVal End Get Set(newvalue As Integer) pVal = newvalue RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("value")) End Set End Property Public Property maximum As Integer Get Return pMax End Get Set(newvalue As Integer) pMax = newvalue RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("maximum")) End Set End Property End Class
All Replies
-
Friday, May 20, 2011 1:35 PM
your binding code or xaml please?
-
Friday, May 20, 2011 1:48 PM
An instance of ProgressUpdater is set as private in the code-behind class:
Private pPU As New ProgressUpdater
Then the binding is set in the constructor:
busy.DataContext = pPU
Then the maximum is set to the size of the file being uploaded and the BusyIndicator is shown:
pPU.maximum = pFileLen busy.IsBusy = TrueThen every time a piece of the file is uploaded it sets the value of the ProgressUpdater to the offset in the file:
pPU.value = pOffset
I've put in breakpoints and the value does get updated, the progress bar just doesn't show any change.
-
Friday, May 20, 2011 1:53 PM
I recall there was something to do with the blocking of UI main thread. Does it get updated eventually after the process code done?
-
Friday, May 20, 2011 2:02 PM
No, at the end of the upload I set IsBusy to False and the BusyIndicator goes away, never having moved from its original value.
I'd be surprised if it was blocking, since so much in Silverlight is asynchronous.
-
Friday, May 20, 2011 2:05 PM
I maybe wrong on this. Sometimes my memory was a mess due to workload and love to hanging out on this board.

-
Friday, May 20, 2011 4:31 PM
Your code looks fine and this example does update the UI through the use of some test buttons.
MainPage XAML:
<UserControl x:Class="ProgressBar.MainPage" 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:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <StackPanel x:Name="LayoutRoot" Background="White"> <toolkit:BusyIndicator Name="busy" BusyContent="{Binding}"> <toolkit:BusyIndicator.BusyContentTemplate> <DataTemplate> <StackPanel> <TextBlock Text="Uploading..." HorizontalAlignment="Center" /> <ProgressBar Value="{Binding value}" Maximum="{Binding maximum}" Height="15" /> </StackPanel> </DataTemplate> </toolkit:BusyIndicator.BusyContentTemplate> <!-- Remove unnecessary default ProgressBar --> <toolkit:BusyIndicator.ProgressBarStyle> <Style TargetType="ProgressBar"> <Setter Property="Visibility" Value="Collapsed" /> </Style> </toolkit:BusyIndicator.ProgressBarStyle> <Grid Name="grdPage"> <!-- Page contents in here --> </Grid> </toolkit:BusyIndicator> <Button Content="Go to 25" Click="Button_Click" /> <Button Content="Go to 50" Click="Button_Click_1" /> <Button Content="Go to 75" Click="Button_Click_2" /> <Button Content="Go to 100" Click="Button_Click_3" /> </StackPanel> </UserControl>MainPage code-behind:
Imports System.ComponentModel Partial Public Class MainPage Inherits UserControl Private pPU As New ProgressUpdater Public Sub New() InitializeComponent() busy.DataContext = pPU pPU.maximum = 100 busy.IsBusy = True End Sub Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) pPU.value = 25 End Sub Private Sub Button_Click_1(sender As System.Object, e As System.Windows.RoutedEventArgs) pPU.value = 50 End Sub Private Sub Button_Click_2(sender As System.Object, e As System.Windows.RoutedEventArgs) pPU.value = 75 End Sub Private Sub Button_Click_3(sender As System.Object, e As System.Windows.RoutedEventArgs) pPU.value = 100 End Sub End Class Public Class ProgressUpdater Implements INotifyPropertyChanged Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Private pVal As Integer, pMax As Integer Public Property value As Integer Get Return pVal End Get Set(newvalue As Integer) pVal = newvalue RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("value")) End Set End Property Public Property maximum As Integer Get Return pMax End Get Set(newvalue As Integer) pMax = newvalue RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("maximum")) End Set End Property End ClassHow are you doing the file uploads? Are you sure this isn't happening on the UI thread? Are you using a BackgroundWorker? Please post the file upload code too so we can test that out.
Brice
-
Friday, May 20, 2011 4:52 PM
The upload is done using a Web Service, so it's not anything I can send you.

It's all asynchronous though.
In the constructor I set up event handlers for the WS methods I'll be using:
AddHandler api.startLargeDocumentUploadCompleted, AddressOf api_startLargeDocumentUploadCompleted AddHandler api.uploadLargeDocumentChunkCompleted, AddressOf api_uploadLargeDocumentChunkCompleted AddHandler api.finishUpload_CreatePolicyDocCompleted, AddressOf api_finishUpload_CreatePolicyDocCompletedThen when the user starts the upload I get the file length and then make an async call to tell the server to get ready to receive a file:
api.startLargeDocumentUploadAsync(pFileLen)
When the completed event is raised, I open the file that I'm uploading as a stream and then start uploading chunks of the file:
Private Sub api_startLargeDocumentUploadCompleted(sender As Object, e As startLargeDocumentUploadCompletedEventArgs) If e.Error Is Nothing Then pUploadID = e.Result Try pUploadStream = pFileToUpload.OpenRead() Catch ex As IOException enableControls() Dim frmMsgBox As New MessageBox("The selected file is locked by another program. Please close the file and try again.", "New Policy", MessageBox.MessageBoxIcon.ErrorIcon, MessageBox.MessageBoxType.OK) frmMsgBox.Show() busy.IsBusy = False Return End Try uploadChunk() Else busy.IsBusy = False pUploadStream.Close() Dim se As SOAPException = defaultExceptionHandler(e.Error) If Not se Is Nothing Then Throw se End If End If End SubTo upload a chunk of the file I first read some of the file asynchronously:
Private Sub uploadChunk() If pOffset = pFileLen Then pUploadStream.Close() If pUploadType = UploadType.Document Then api.finishUpload_CreatePolicyDocAsync(pUploadID, pFileToUpload.Extension, pPolicy) End If Return End If If pFileLen - pOffset < pChunkLen Then pChunkLen = pFileLen - pOffset End If Array.Resize(pChunk, pChunkLen) pUploadStream.BeginRead(pChunk, 0, pChunkLen, AddressOf cbUploadStreamRead, Nothing) pOffset += pChunkLen pPU.value = pOffset End SubWhen the completed event is raised, I upload that chunk of the file with another async call:
Private Sub cbUploadStreamRead(ar As IAsyncResult) pUploadStream.EndRead(ar) api.uploadLargeDocumentChunkAsync(pUploadID, pChunk) End SubWhen that completed event is raised, I call the method to read and upload the next chunk.
Private Sub api_uploadLargeDocumentChunkCompleted(sender As Object, e As AsyncCompletedEventArgs) If e.Error Is Nothing Then uploadChunk() Else pUploadStream.Close() Dim se As SOAPException = defaultExceptionHandler(e.Error) If Not se Is Nothing Then Throw se End If End If End SubWhen the whole file has been uploaded, the uploadChunk method makes a different async call to tell the server that the upload is finished and how to file the document. -
Monday, May 23, 2011 11:25 PM
<ProgressBar Value="{Binding value}" Maximum="{Binding maximum}" Height="15" />
You need to create a ValueChanged event to your ProgressBar, and check when the value comes to the maximum, set the IsBusy property of the BusyIndicator to false.
Hope you can understand.
-
Wednesday, May 25, 2011 8:58 AM
That would automatically switch off the BusyIndicator when the progress reached 100%, but doesn't address my actual problem, which is the progress bar not updating when the value changes
-
Wednesday, May 25, 2011 1:03 PM
Wow, actually just implementing the ValueChanged event got it working
-
Friday, September 09, 2011 2:45 PM
Hi! I have the same problem, I've tried that you did but I still getting the progress bar without moving....can you help me please?

