C# | How to implement video (MediaElement) in WPF Prism using the MVVM pattern

How to implement video playback (MediaElement.Play()) in WPF Prism using the MVVM pattern.

TechPublished 1 min read

This explains how to implement video playback (MediaElement.Play()) in WPF Prism using the MVVM pattern.

IMediaService interface

  1. Introduce an interface called IMediaService.
public Interface IMediaService
{
    void Play();
    void Pause();
    void Stop();
    void Rewind();
    void FastForward();
    bool IsPlaying();
}

View code-behind

  1. Implement IMediaService on the view.
public partial class DemoView : UserControl, IMediaService
{
    public DemoView()
    {
        InitializeComponent();
    }

    void IMediaService.FastForward()
    {
        this.MediaPlayer.Position += TimeSpan.FromSeconds(10);
    }

    void IMediaService.Pause()
    {
        this.MediaPlayer.Pause();
    }

    void IMediaService.Play()
    {
        this.MediaPlayer.Play();
    }

    void IMediaService.Rewind()
    {
        this.MediaPlayer.Position -= TimeSpan.FromSeconds(10);
    }

    void IMediaService.Stop()
    {
        this.MediaPlayer.Stop();
    }

    bool IMediaService.IsPlaying()
    {
        // ローディング完了時はtrue
        return this.MediaPlayer.Position < this.MediaPlayer.NaturalDuration;
    }
}

View Xaml

  1. Next, add some code to DemoView.XAML.
  • Name the MediaElement so the code-behind can access it as shown above.
    <MediaElement Source="{Binding CurrentMedia}" x:Name="MediaPlayer"/>

  • Name the view itself so it can be passed as a parameter.

  • Import the interactivity namespace (other required namespaces are omitted).

   <UserControl x:Class="Test.DemoView"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
     x:Name="MediaService">
  • Wire up the Loaded event through a trigger, and pass the view itself (x:Name=MediaService) to the view model through a command.
   <i:Interaction.Triggers>
         <i:EventTrigger EventName="Loaded">
             <i:InvokeCommandAction Command="{Binding MediaServiceLoaded}" CommandParameter="{Binding ElementName=MediaService}"></i:InvokeCommandAction>
         </i:EventTrigger>
     </i:Interaction.Triggers>
  • Prepare buttons (commands) to operate the MediaElement.
   <Button Command="{Binding MoviePlayButton}" Content="Play"></Button> 
   <Button Command="{Binding MovieStopButton}" Content="Stop"></Button> 

ViewModel

  1. Make it possible to call the MediaElement's methods from the ViewModel.
public class DemoViewModel : BindableBase
{
    public DemoViewModel()
    {
        MediaServiceLoaded = new DelegateCommand<IMediaService>(MediaServiceLoadedExecute);
        MoviePlayButton = new DelegateCommand(MoviePlayButtonExecute);

        // ...
    }

    public IMediaService MediaService {get; private set;}

    public DelegateCommand<IMediaService> MediaServiceLoaded { get; }
    private void MediaServiceLoadedExecute(IMediaService mediaService)
    {
        this.MediaService = mediaService;
    }

    public DelegateCommand MoviePlayButton { get; }
    private void MoviePlayButtonExecute()
    {
        if (MediaService == null)
        {
            return;
        }

        MediaService.Play();
    }

    // ...
}

By following these steps, you can play and stop the MediaElement from within the ViewModel.
It requires a bit of code in the code-behind, but I think the resulting code still respects the MVVM pattern.