The ProgressBar pretty much does what it says on the tin, displays progress, in a bar form (well, by default anyhow). It’s pretty simple to use: <ProgressBar Minimum="0" Maximum="100" Value="50"/>
Gives you a progress bar with 50% of it filled:
Easy! But of course, we’re wanting to use binding to change the value, again, pretty easy, have a ViewModel with a ‘Value’ in it, and bind:
<ProgressBar Minimum="0" Maximum="100" Value="{Binding Value}"/>
Spiffy, and whilst we’re at it, why not bind the Maximum value as well – after all, we can’t be sure of the size of the progress, and it’s a pain to have to work out the percentage (when the progress bar can do it for us):
<ProgressBar Minimum="0" Maximum="MaximumValue" Value="{Binding Value}"/>
Right, this will work absolutely fine. Or will it??? On the face of it, it looks good, and testing it shows no issues, until at one point we go from:
Maximum = 100;
Value = 90;
to
Maximum=60;
Value=50;
On the face of it not unreasonable. The problem is more obvious if we look at the states of the properties after each set (initially Maximum is set at 1, Value = 0):
Code
Maximum
Value
Value < Maximum
Maximum = 100;
100
0
True
Value = 90;
100
90
True
Maximum = 60;
60
90
False
Value = 50;
60
50
True
Everything is good until the Value is less than the Maximum, at this point the Progress Bar breaks. That’s right, it no longer updates itself, it will always look 100% full.
The simple solution – always ensuring you set Value before Maximum is fine unless you’re using a ProgressBar in a less controlled environment – where for example you’re setting a ‘container’ with both values at the same time.
The example I have is in a DataTemplate, I have a DataTemplate for a BusyIndicator, (specifically the BusyContentTemplate). The binding works this way:
<BusyIndicator BusyContent="{Binding BusyContent}" BusyContentTemplate="{Binding ProgressTemplate}"/>
With the template as the ProgressBar defined above… I was setting my BusyContent like this:
BusyContent = content;
aaaaaand finally, ‘content’ is a class:
public class ContentClass : INotifyPropertyChanged
{
//Obviously this is properly implemented…
public double Maximum { get;set;}
public double Value { get;set;}
}
Soooo… As I was replacing the BusyContent wholesale, the order of the binding being set was outside of my control, so – how to go about it? Basically? Fudge it. Modify the ContentClass to include a method:
public void Update(double value, double max)
{
Value = value;
Maximum = max;
}
and change where the setting is to be:
BusyContent.Update(content.Value, content.Maximum);
Thereby getting the order correct.. Obvious really. Meh :|