What is the Duration Object in WPF?

In WPF, Duration is a struct that represents the length of time that an operation (like an animation or a media playback) should take. Unlike a plain TimeSpan, a Duration can express not just a fixed time interval, but also special states:

  1. A specific TimeSpan: The most common case, representing a fixed length of time (e.g., 5 seconds, 2 minutes).

  2. Automatic: Indicates that the duration is determined automatically by the system or the content.

  3. Forever: Indicates that the duration is infinite; the operation will continue indefinitely.

Why does Duration exist instead of just TimeSpan?

While TimeSpan is excellent for fixed durations, it can’t express “automatic” or “forever” concepts. WPF needed a way to specify these behaviors, especially for:

  • Animations: An animation might have a fixed duration (e.g., animate over 2 seconds), or it might run Forever, or its duration might be Automatic (meaning it runs for the natural duration of its target, like a video).

  • Media Playback: A MediaElement‘s NaturalDuration property needs to indicate if it has a known length (TimeSpan), or if it’s a live stream with an Automatic (or unknown/infinite) duration.

Key Properties of Duration

  1. HasTimeSpan: A bool property. Returns true if the Duration represents a specific TimeSpan value; false otherwise (i.e., if it’s Automatic or Forever).

  2. TimeSpan: A TimeSpan property. If HasTimeSpan is true, this property returns the underlying TimeSpan value. If HasTimeSpan is false, accessing this property will throw an InvalidOperationException. You must check HasTimeSpan before trying to access this.

  3. Automatic (Static Property): A static read-only property that returns a Duration struct representing an automatic duration.

  4. Forever (Static Property): A static read-only property that returns a Duration struct representing an infinite duration.

Creating Duration Objects

You can create Duration objects in a few ways:

  1. From a TimeSpan (most common):

  1.  

Duration fiveSeconds = new Duration(TimeSpan.FromSeconds(5));
Duration twoMinutes = new Duration(new TimeSpan(0, 2, 0));
// hours, minutes, seconds
  1. ​Using Automatic or Forever static properties:

Duration automaticDuration = Duration.Automatic;
Duration infiniteDuration = Duration.Forever;

Common Use Cases and Examples

1. MediaElement.NaturalDuration

This is the most direct connection to our previous discussions. The NaturalDuration property of a MediaElement is a Duration struct.

using System;
using System.Windows.Media; // For MediaElement

// Inside your MediaElement_MediaOpened event handler:
private void MyMediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
    // Check if the media has a definite length
    if (MyMediaElement.NaturalDuration.HasTimeSpan)
    {
        // If it does, access the TimeSpan component
        TimeSpan totalLength = MyMediaElement.NaturalDuration.TimeSpan;
        MessageBox.Show($"Media has a duration of: {totalLength.Minutes:D2}:{totalLength.Seconds:D2}");

        // Now you can use this totalLength to set the Maximum of a slider, for example
        // PositionSlider.Maximum = totalLength.TotalSeconds;
    }
    else if (MyMediaElement.NaturalDuration == Duration.Automatic)
    {
        MessageBox.Show("Media duration is Automatic (e.g., live stream).");
    }
    else if (MyMediaElement.NaturalDuration == Duration.Forever)
    {
        MessageBox.Show("Media duration is Forever (e.g., infinite loop).");
    }
}

2. Animations (e.g., DoubleAnimationStoryboard)

The Duration property is fundamental for controlling the length of animations in WPF.

XAML Example (Animating a Rectangle’s Width):

C# Example (Programmatically Starting an Animation with Forever):

<Window x:Class="DurationDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Duration Animation Demo" Height="250" Width="400">
    <StackPanel Margin="20" HorizontalAlignment="Center">
        <Rectangle x:Name="MyRectangle" Fill="Blue" Width="50" Height="50" Margin="20">
            <Rectangle.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="MyRectangle"
                                             Storyboard.TargetProperty="Width"
                                             From="50" To="200"
                                             Duration="0:0:3"  AutoReverse="True" RepeatBehavior="Forever"/>

                            <DoubleAnimation Storyboard.TargetName="MyRectangle"
                                             Storyboard.TargetProperty="Height"
                                             From="50" To="150"
                                             Duration="0:0:5"
                                             AutoReverse="True" RepeatBehavior="Forever"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Rectangle.Triggers>
        </Rectangle>

        <Button Content="Start Forever Animation" Click="StartForeverAnimation_Click" Margin="0,20,0,0"/>
    </StackPanel>
</Window>

​C# Example (Programmatically Starting an Animation with Forever):

using System;
using System.Windows;
using System.Windows.Media.Animation; // For DoubleAnimation, Storyboard

namespace DurationDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void StartForeverAnimation_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation opacityAnimation = new DoubleAnimation
            {
                From = 1.0,
                To = 0.2,
                Duration = Duration.Forever, // This animation will run indefinitely
                AutoReverse = true,
                RepeatBehavior = RepeatBehavior.Forever
            };

            Storyboard storyboard = new Storyboard();
            storyboard.Children.Add(opacityAnimation);
            Storyboard.SetTargetName(opacityAnimation, MyRectangle.Name); // Link animation to Rectangle
            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(Rectangle.OpacityProperty));

            // Start the storyboard
            storyboard.Begin(MyRectangle); // Begin the storyboard on the Rectangle
        }
    }
}

In the XAML for animation, Duration="0:0:3" is a shorthand notation that WPF recognizes as a TimeSpan value.

Key Takeaway

Duration is WPF’s flexible way to specify the length of time-based operations, allowing for fixed TimeSpan values, or the special Automatic and Forever states, which are particularly useful for dynamic content like media or continuous animations. Always check HasTimeSpan before trying to get the TimeSpan value from a Duration object.

Ads