Search code examples
wpfanimationstoryboardmediaelement

Combining MediaTimeline with animation in Storyboard programmatically


I am trying to use MediaTimeline and DoubleAnimation inside Storyboard to play audio with animation. Everything is implemented in C# without XAML. Nothing happens after Storyboard.Begin is called in the code below and no exception is thrown. mediaElement's HasAudio property is false and MediaOpened event of MediaElement is never called. It seems mediaElement can't load the audio file. I don't know whether MediaElement or MediaTimeline is responsible for loading the audio. DoubleAnimation works fine without the MediaTimeline. What am I missing here?

private void SetStoryboard(double beginLeft, double endLeft, TimeSpan duration)
{
        mediaElement = new MediaElement();
        mediaElement.LoadedBehavior = MediaState.Manual;
        mediaElement.ScrubbingEnabled = true;
        mediaElement.MediaOpened += new RoutedEventHandler(MediaElement_MediaOpened);

        mediaTimeline = new MediaTimeline();
        mediaTimeline.Duration = new Duration(duration);
        mediaTimeline.Source = new Uri(musicFilePath);
        mediaTimeline.FillBehavior = FillBehavior.Stop;
        Storyboard.SetTarget(mediaTimeline, mediaElement);

        anim = new DoubleAnimation();
        anim.From = beginLeft;
        anim.To = endLeft;
        anim.Duration = new Duration(duration);
        anim.FillBehavior = FillBehavior.Stop;
        Storyboard.SetTarget(anim, slider);
        Storyboard.SetTargetProperty(anim, new PropertyPath(Canvas.LeftProperty));

        storyboard = new Storyboard();
        storyboard.SlipBehavior = SlipBehavior.Slip;
        storyboard.Children.Add(mediaTimeline);
        storyboard.Children.Add(anim);

        storyboard.Begin(this, true);
}

Solution

  • Your MediaElement is not part of the VisualTree. You are constructing it but as it is not assigned to the visual tree it will never get used by the Layout System.

    You can either add it in code-Behind by adding it to a valid container element. e.g.

    XAML:

    <Grid x:Name="parentGrid">
    

    Code-behind:

    var mediaElement = new MediaElement();
    parentGrid.Children.Add(mediaElement);
    

    Or you can place the MediaElement on your page/window, remove the line where you construct the MediaElement ( .. = new MediaElement) and just access it via code-behind:

    XAML:

    <MediaElement x:Name="mediaElement" Width="200" Height="100"/>