Home > Enterprise >  Get ProgressBar Value
Get ProgressBar Value

Time:10-24

I am Trying to implement a ProgressBar in WPF and figured it would be nice to show the percentage as a percentage on the bar itself.

I found out that the ProgressBar conveniently already does calculations for the display in the background. So let's say I have a max value of 12 and the current value is 6, is shows a progress bar which is already half/50% full.

ProgessBar that is half filled.

Unfortunately the value of the ProgressBar is still 6 (because it is the sixth element of 12)

ProgessBar that is half filled with an overlay text that says "6%".

Is there an easy way to get the percentage value of the progress bar, or do I have to do the calculations on my own and databind a double variable to the TextBox and ProgressBar?

This is the XAML code I have so far:

        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <Grid Margin="20">
                <ProgressBar Name="ProgrBar"  Minimum="0" Maximum="12" Value="6" Height="30"/>
                <TextBlock Text="{Binding ElementName=ProgrBar, Path=Value, StringFormat={}{0}% }" HorizontalAlignment="Center"></TextBlock>
            </Grid>
        </StackPanel>

    </Grid>
</Window>

CodePudding user response:

The ProgressBar does not know how to display percentages. It has a Minimum and a Maximum property that only define the bounds within the Value is expected. All are of type double, but their interpretation is up to you. It could be percentages, steps in a process, number of items, you name it.

If the percentage is data from a model in your context, you could expose it from the view model, but if it is only for display purposes, you could create a value converter that takes the limits and value and returns a formatted percentage string.

public class PercentageConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      if (values.Length != 3 ||
          !(values[0] is double minimum) ||
          !(values[1] is double maximum) ||
          !(values[2] is double value) ||
          minimum > maximum ||
          value < minimum ||
          value > maximum)
         return Binding.DoNothing;

      var percentage = (value - minimum) / (maximum - minimum);
      return percentage.ToString("P0");
   }

   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
   {
      throw new NotImplementedException();
   }
}

The converter is a multi-value converter to be able to bind multiple properties. It checks the bounds before calculation to rule out weird results in case of invalid input. The format specifier is P0.

Create an instance of the converter in a resource dictionary in scope and use it in a MultiBinding.

<Grid Margin="20">
   <Grid.Resources>
      <local:PercentageConverter x:Key="PercentageConverter"/>
   </Grid.Resources>
   <ProgressBar Name="ProgrBar"  Minimum="0" Maximum="12" Value="6" Height="30"/>
   <TextBlock HorizontalAlignment="Center">
      <TextBlock.Text>
         <MultiBinding Converter="{StaticResource PercentageConverter}">
            <Binding ElementName="ProgrBar" Path="Minimum"/>
            <Binding ElementName="ProgrBar" Path="Maximum"/>
            <Binding ElementName="ProgrBar" Path="Value"/>
         </MultiBinding>
      </TextBlock.Text>
   </TextBlock>
</Grid>

Since this is a type of control that you might want to reuse, you could think about extracting it into a UserControl or even custom control if you want to enable templating. Then you could make the display of results toggleable with a property, e.g. DisplayPercentage or allow for custom converters similar to this one. This could prevent a lot of copy-paste and duplicated code in the long run, keep it DRY.

CodePudding user response:

Is there an easy way to get the percentage value of the progress bar

No, because it's not stored somewhere.

or do I have to do the calculations on my own ...

Yes. Bind the TextBlock to a property that returns the value of the expression ProgrBar.Maximum / ProgrBar.Value.

  • Related