Before I get into the details here, I'm still in what I would consider to be the "learning" phase of my C#/WPF journey... so apologies if what I'm asking here is stupidly obvious... I have a small application (WPF, .NET Framework 4.8) that does the following:
- read a list of values
- do something for each value in the list
I am trying to do this with a BackgroundWorker so that I can report back to the UI as the list is being processed, preferably with a progress bar.
For the moment, the DoWork method just has some code in there to indicate that it's actually going through the process as expected and so that I could check that all the UI is updating as expected before I put the actual "what I want it to do" in there.
It seems that all the properties are updating as expected, but the UI (i.e. the progress bar) just doesn't move. And I have checked that the data context in the XAML is set correctly (both in the XAML and in the Code-Behind).
In my XAML I have the following:
<ProgressBar x:Name="ProgressBar"
Width="740"
Height="20"
Background="Transparent"
Foreground="#008DEB"
Grid.Row="3"
Minimum="0"
Maximum="100"
Value="{Binding ProgressBarIndicator}"/>
And in my class containing all my methods/properties etc, I have:
private int _measurementProgress;
public int MeasurementProgress
{
get { return _measurementProgress; }
set
{
_measurementProgress = value;
OnPropertyChanged();
}
}
private int _progressBarIndicator;
public int ProgressBarIndicator
{
get { return _progressBarIndicator; }
set
{
_progressBarIndicator = value;
OnPropertyChanged();
}
}
public void StartMeasurements(string ipAddress)
{
TotalMeasurementsInList = CommandsList.Count;
MeasurementProgress = 0;
measurementWorker.WorkerReportsProgress = true;
measurementWorker.DoWork += worker_DoWork;
measurementWorker.ProgressChanged += worker_ProgressChanged;
measurementWorker.RunWorkerCompleted += worker_RunWorkerCompleted;
measurementWorker.RunWorkerAsync();
}
public void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (var command in CommandsList)
{
MessageBox.Show(String.Format("Measuring Sample: {0}",command.SampleName),"Measuring Sample");
measurementWorker.ReportProgress((int)((double)(MeasurementProgress / (double)TotalMeasurementsInList)*100));
Thread.Sleep(command.DelayTime*1000);
}
}
public void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MeasurementProgress++;
MessageBox.Show(String.Format("Progress is {0}%", e.ProgressPercentage.ToString()));
ProgressBarIndicator = e.ProgressPercentage;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ProgressBarIndicator = 100;
MessageBox.Show("Measurements are completed","Finished");
}
The "OnPropertyChanged()" method is inside my ObservableObject class, and the above class is set to inherit from this ObservableObject class. The ObservableObject class looks like this:
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyname = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
}
By placing break-points in strategic places, I can confirm that the value of MeasurementProgress does indeed increment as one would expect, as does the value of ProgressBarIndicator. This was double-confirmed by the MessageBox in the worker_ProgressChanged method as it does indeed display the appropriate percentage value.
Annoyingly, what would appear to me to be exactly the same code is working as expected in another part of the application. The code here is more or less a copy/paste from there... but I just can't see what I'm doing wrong.
Any help or pointers where I could look to try and debug this appreciated.
Many thanks
Colin