Page 1 of 1

Animated ProgressBar

Posted: 24 Sep 2021, 00:00
by extsmichalak
Hey!
Is it possible to animate the dynamic value that's passed to `ProgressBar`? For example I found such solution here: viewtopic.php?f=3&t=2081&p=11609&hilit= ... bar#p11609 but it doesn't work for me:
<ProgressBar
        x:Name="CustomProgressBar"
        Style="{DynamicResource LoadingBar}"
        Width="..."
        Height="..."
        Foreground="..."
        Background="..."
        Maximum="1"
        Minimum="0"
        Orientation="Horizontal"
        Value="{Binding progress}">
        <ProgressBar.Triggers>
          <EventTrigger RoutedEvent="RangeBase.ValueChanged">
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation
                  Storyboard.TargetProperty="Value"
                  To="{Binding progress}"
                  Duration="0:0:3" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger>
        </ProgressBar.Triggers>
      </ProgressBar>
Do I have to add custom Behavior for ProgressBar or create my own custom ProgressBar? Thanks

Re: Animated ProgressBar

Posted: 24 Sep 2021, 11:02
by sfernandez
You just need to bind the viewmodel property to a different property (Tag or any attached property you defined) and animate the Value property of the progress bar when that other property changes:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions">
  <ProgressBar x:Name="progress" Width="400" Height="30" Minimum="0" Maximum="500" Tag="{Binding Value, ElementName=source}">
    <i:Interaction.Triggers>
      <ei:PropertyChangedTrigger Binding="{Binding Tag, ElementName=progress}">
        <ei:ControlStoryboardAction>
          <ei:ControlStoryboardAction.Storyboard>
            <Storyboard>
              <DoubleAnimation To="{Binding Value, ElementName=source}" Duration="0:0:0.3"
                               Storyboard.TargetProperty="Value" Storyboard.TargetName="progress"/>
            </Storyboard>
          </ei:ControlStoryboardAction.Storyboard>
        </ei:ControlStoryboardAction>
      </ei:PropertyChangedTrigger>
    </i:Interaction.Triggers>
  </ProgressBar>
  <Slider x:Name="source" Minimum="0" Maximum="500" Width="200"
    VerticalAlignment="Bottom" Margin="10" IsMoveToPointEnabled="True"/>
</Grid>
You can also encapsulate this inside a Behavior that fires the animation internally when its own property changes:
<ProgressBar Style="{DynamicResource LoadingBar}">
  <i:Interaction.Behaviors>
    <local:AnimatedProgressBehavior Progress="{Binding progress}"/>
  </i:Interaction.Behaviors>
</ProgressBar>
public class AnimatedProgressBehavior: Behavior<ProgressBar>
{
  ...
  private void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    AnimatedProgressBehavior behavior = (AnimatedProgressBehavior)d;
    if (behavior.AssociatedObject != null)
    {
      behavior.animation.To = (float)e.NewValue;
      behavior.storyboard.Begin(behavior.AssociatedObject);
    }
  }
}

Re: Animated ProgressBar

Posted: 24 Sep 2021, 18:12
by extsmichalak
Thank you @sfernandez! Tested out XAML way and it works perfectly

Re: Animated ProgressBar

Posted: 27 Sep 2021, 09:42
by sfernandez
Great, I'm marking this as solved.