Wrapper for System.Windows.Controls.MediaElement.
MediaState
)Timespan?
)Timespan?
)bool?
)int?
)int?
)bool?
)bool?
)bool
)double
)bool
)double
)double
)double
)Uri
)double
)double
)bool
)bool
)Stretch
)StretchDirection
)MediaState
)The wrapper wraps the properties of System.Windows.Controls.MediaElement and adds a couple of new properties. Mapped properties are dependency properties that are updated when needed.
MediaState
)The current MediaState
of the player.
Timespan?
)The current position in the media, null
if no media is loaded.
Twoway bindable and updates every 0.1 s when playing.
Timespan?
)The length of the current media, null
if no media is loaded.
bool?
)Mapped to System.Windows.Controls.MediaElement.CanPause, null
if no media is loaded.
int?
)Mapped to System.Windows.Controls.MediaElement.NaturalVideoHeight, null
if no media is loaded.
int?
)Mapped to System.Windows.Controls.MediaElement.NaturalVideoWidth, null
if no media is loaded.
bool?
)Mapped to System.Windows.Controls.MediaElement.HasAudio, null
if no media is loaded.
bool?
)Mapped to System.Windows.Controls.MediaElement.HasVideo, null
if no media is loaded.
bool
)Returns true if media is loaded.
double
)Mapped to System.Windows.Controls.MediaElement.SpeedRatio.
bool
)Mapped to System.Windows.Controls.MediaElement.IsBuffering.
double
)Mapped to System.Windows.Controls.MediaElement.DownloadProgress. Updated every 1 s when buffering.
double
)Mapped to System.Windows.Controls.MediaElement.BufferingProgress. Updated every 1 s when buffering.
double
)How much volume is changed when MediaCommands.IncreaseVolume & MediaCommands.DecreaseVolume are invoked. Default 0.05;
A list of video file formats for convenience. .dat; .wmv; .3g2; .3gp; .3gp2; .3gpp; .amv; .asf; .avi; .bin; .cue; .divx; .dv; .flv; .gxf; .iso; .m1v; .m2v; .m2t; .m2ts; .m4v; .mkv; .mov; .mp2; .mp2v; .mp4; .mp4v; .mpa; .mpe; .mpeg; .mpeg1; .mpeg2; .mpeg4; .mpg; .mpv2; .mts; .nsv; .nuv; .ogg; .ogm; .ogv; .ogx; .ps; .rec; .rm; .rmvb; .tod; .ts; .tts; .vob; .vro; .webm
Usage:
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = $"Media files|{this.MediaElement.VideoFormats}|All files (*.*)|*.*"
};
if (openFileDialog.ShowDialog() == true)
{
this.MediaElement.Source = new Uri(openFileDialog.FileName);
}
A list of audio file formats for convenience. .mp3; .wma; .aac; .adt; .adts; .m4a; .wav; .aif; .aifc; .aiff; *.cda
Usage:
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = $"Media files|{this.MediaElement.AudioFormats}|All files (*.*)|*.*"
};
if (openFileDialog.ShowDialog() == true)
{
this.MediaElement.Source = new Uri(openFileDialog.FileName);
}
Uri
)Mapped to System.Windows.Controls.MediaElement.Source.
When source changes play is invoked to trigger load. Then pause is invoked in the MediaOpened event.
This results in the video paused at the first frame as initial state after setting Source
Subscribe to MediaOpened
if you want to start playing on load.
double
)Mapped to System.Windows.Controls.MediaElement.Volume.
double
)Mapped to System.Windows.Controls.MediaElement.Balance.
bool
)Mapped to System.Windows.Controls.MediaElement.IsMuted.
bool
)Mapped to System.Windows.Controls.MediaElement.ScrubbingEnabled.
Stretch
)Mapped to System.Windows.Controls.MediaElement.Stretch.
StretchDirection
)Mapped to System.Windows.Controls.MediaElement.StretchDirection.
MediaState
)Set initial state after media is loaded. This is very unlike MediaElement.LoadedBehavior where setting it to paused will throw if touching play.
Mapped to System.Windows.Controls.MediaElement.MediaFailed.
Mapped to System.Windows.Controls.MediaElement.MediaOpened.
Mapped to System.Windows.Controls.MediaElement.BufferingStarted.
Mapped to System.Windows.Controls.MediaElement.BufferingEnded.
Mapped to System.Windows.Controls.MediaElement.ScriptCommand.
Mapped to System.Windows.Controls.MediaElement.MediaEnded.
Command bindings for:
If parameter is null the value of VolumeIncrement is used.
If parameter is null
the value of SkipIncrement is used.
If parameter is an int
the value of parameter*SkipIncrement is used.
If parameter is double
`TimeSpan.FromSeconds(parameter) is used.
If parameter is TimeSpan it is used.
Values can be negative.
For using mousewheel in inputbindings
<MouseBinding Command="media:Commands.SkipBack" CommandTarget="{Binding ElementName=MediaElement}">
<MouseBinding.Gesture>
<media:MouseWheelGesture Direction="Down" />
</MouseBinding.Gesture>
</MouseBinding>
And with modifier
<MouseBinding Command="media:Commands.SkipBack"
CommandParameter="60"
CommandTarget="{Binding ElementName=MediaElement}">
<MouseBinding.Gesture>
<media:MouseWheelGesture Direction="Down" Modifiers="Control" />
</MouseBinding.Gesture>
</MouseBinding>
Exposes a Geometry
attached property.
<Button media:Icon.Geometry="{StaticResource {x:Static media:Geometries.PlayGeometryKey}}"
Command="Play"
CommandTarget="{Binding ElementName=MediaElement}" />
Exposes a PauseWhileDragging
attached property.
When binidng this to a MediaElementWrapper
playback is paused while dragging.
<Slider x:Name="ProgressSlider"
Grid.Row="0"
media:Drag.PauseWhileDragging="{Binding ElementName=MediaElement}"
Maximum="{Binding ElementName=MediaElement,
Path=Length,
Converter={x:Static demo:TimeSpanToSecondsConverter.Default}}"
Minimum="0"
Style="{StaticResource {x:Static media:Styles.ProgressSliderStyleKey}}"
Value="{Binding ElementName=MediaElement,
Path=Position,
Converter={x:Static demo:TimeSpanToSecondsConverter.Default}}" />
Converts Timespans like this:
Time | Result |
---|---|
null | -:-- |
00:00:01 | 0:01 |
00:00:12 | 0:12 |
00:01:23 | 1:23 |
00:12:34 | 12:23 |
01:23:45 | 1:23:45 |
MediaElementWrapper has a command bindings for:
<Window x:Class="Gu.Wpf.Media.Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:media="https://github.com/JohanLarsson/Gu.Wpf.Media"
Title="MainWindow"
MinWidth="300"
Background="Black"
SizeToContent="WidthAndHeight"
mc:Ignorable="d">
<Window.InputBindings>
<KeyBinding Key="Space"
Command="TogglePlayPause"
CommandTarget="{Binding ElementName=MediaElement}" />
<KeyBinding Key="F11" Command="media:Commands.ToggleFullScreen" />
<KeyBinding Key="Escape" Command="media:Commands.EndFullScreen" />
<KeyBinding Key="Left"
Command="media:Commands.SkipBack"
CommandTarget="{Binding ElementName=MediaElement}" />
<MouseBinding Command="media:Commands.SkipBack" CommandTarget="{Binding ElementName=MediaElement}">
<MouseBinding.Gesture>
<media:MouseWheelGesture Direction="Down" />
</MouseBinding.Gesture>
</MouseBinding>
<KeyBinding Key="Left"
Command="media:Commands.SkipBack"
CommandParameter="60"
CommandTarget="{Binding ElementName=MediaElement}"
Modifiers="Control" />
<MouseBinding Command="media:Commands.SkipBack"
CommandParameter="60"
CommandTarget="{Binding ElementName=MediaElement}">
<MouseBinding.Gesture>
<media:MouseWheelGesture Direction="Down" Modifiers="Control" />
</MouseBinding.Gesture>
</MouseBinding>
<KeyBinding Key="Right"
Command="media:Commands.SkipForward"
CommandTarget="{Binding ElementName=MediaElement}" />
<MouseBinding Command="media:Commands.SkipForward" CommandTarget="{Binding ElementName=MediaElement}">
<MouseBinding.Gesture>
<media:MouseWheelGesture Direction="Up" />
</MouseBinding.Gesture>
</MouseBinding>
<KeyBinding Key="Right"
Command="media:Commands.SkipForward"
CommandParameter="60"
CommandTarget="{Binding ElementName=MediaElement}"
Modifiers="Control" />
<MouseBinding Command="media:Commands.SkipForward"
CommandParameter="60"
CommandTarget="{Binding ElementName=MediaElement}">
<MouseBinding.Gesture>
<media:MouseWheelGesture Direction="Up" Modifiers="Control" />
</MouseBinding.Gesture>
</MouseBinding>
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Executed="OpenExecuted" />
<CommandBinding Command="media:Commands.ToggleFullScreen" Executed="OnToggleFullScreenExecuted" />
<CommandBinding CanExecute="OnEndFullScreenCanExecute"
Command="media:Commands.EndFullScreen"
Executed="OnEndFullScreenExecuted" />
</Window.CommandBindings>
<Grid>
<media:MediaElementWrapper x:Name="MediaElement"
LoadedBehavior="Play"
ScrubbingEnabled="True"
Stretch="None" />
<Grid VerticalAlignment="Bottom" Background="#19000000">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Slider x:Name="ProgressSlider"
Grid.Row="0"
media:Drag.PauseWhileDragging="{Binding ElementName=MediaElement}"
Maximum="{Binding ElementName=MediaElement,
Path=Length,
Converter={x:Static media:NullableTimeSpanToSecondsConverter.Default}}"
Minimum="0"
Style="{StaticResource {x:Static media:Styles.ProgressSliderStyleKey}}"
Value="{Binding ElementName=MediaElement,
Path=Position,
Converter={x:Static media:NullableTimeSpanToSecondsConverter.Default}}" />
<Grid Grid.Row="1">
<Grid.Resources>
<Style BasedOn="{StaticResource {x:Static media:Styles.PlayerButtonBaseStyleKey}}" TargetType="{x:Type Button}" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="PlayPauseButton"
Grid.Column="0"
IsChecked="{Binding ElementName=MediaElement,
Path=IsPlaying}"
IsEnabled="{Binding ElementName=MediaElement,
Path=HasMedia}">
<ToggleButton.Style>
<Style BasedOn="{StaticResource {x:Static media:Styles.PlayerButtonBaseStyleKey}}" TargetType="{x:Type ToggleButton}">
<Setter Property="media:Icon.Geometry" Value="{StaticResource {x:Static media:Geometries.PauseGeometryKey}}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="media:Icon.Geometry" Value="{StaticResource {x:Static media:Geometries.PlayGeometryKey}}" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<ToggleButton x:Name="ToggleMutedButton"
Grid.Column="1"
IsChecked="{Binding ElementName=MediaElement,
Path=IsMuted}"
IsEnabled="{Binding ElementName=MediaElement,
Path=HasMedia}">
<ToggleButton.Style>
<Style BasedOn="{StaticResource {x:Static media:Styles.PlayerButtonBaseStyleKey}}" TargetType="{x:Type ToggleButton}">
<Setter Property="media:Icon.Geometry" Value="{StaticResource {x:Static media:Geometries.UnMuteGeometryKey}}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="media:Icon.Geometry" Value="{StaticResource {x:Static media:Geometries.MuteGeometryKey}}" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<TextBlock x:Name="ProgressTextBlock"
Grid.Column="2"
VerticalAlignment="Center"
Foreground="{Binding ElementName=ToggleMutedButton,
Path=Foreground}"
Opacity="{Binding ElementName=ToggleMutedButton,
Path=Opacity}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} / {1}">
<Binding Converter="{x:Static media:TimeSpanToStringConverter.Default}"
ElementName="MediaElement"
Path="Position" />
<Binding Converter="{x:Static media:TimeSpanToStringConverter.Default}"
ElementName="MediaElement"
Path="Length" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Button Grid.Column="4"
media:Icon.Geometry="{StaticResource {x:Static media:Geometries.FolderOpenGeometryKey}}"
Command="ApplicationCommands.Open" />
<Button Grid.Column="5"
HorizontalAlignment="Right"
media:Icon.Geometry="{StaticResource {x:Static media:Geometries.FullScreenGeometryKey}}"
Command="media:Commands.ToggleFullScreen"
IsEnabled="{Binding ElementName=MediaElement,
Path=HasMedia}"
Padding="12,6,6,6" />
</Grid>
</Grid>
</Grid>
</Window>
With code behind:
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Win32;
public partial class MainWindow : Window
{
private Stretch stretch;
public MainWindow()
{
this.InitializeComponent();
}
private void OpenExecuted(object sender, ExecutedRoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = $"Media files|{this.MediaElement.VideoFormats}|All files (*.*)|*.*"
};
if (openFileDialog.ShowDialog() == true)
{
this.MediaElement.SetCurrentValue(MediaElementWrapper.SourceProperty, new Uri(openFileDialog.FileName));
}
}
private void OnToggleFullScreenExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (this.WindowStyle == WindowStyle.SingleBorderWindow)
{
this.stretch = this.MediaElement.Stretch;
this.MediaElement.Stretch = Stretch.Uniform;
this.WindowStyle = WindowStyle.None;
this.SizeToContent = SizeToContent.Manual;
this.WindowState = WindowState.Maximized;
}
else
{
this.MediaElement.Stretch = this.stretch;
this.WindowStyle = WindowStyle.SingleBorderWindow;
this.SizeToContent = SizeToContent.WidthAndHeight;
this.WindowState = WindowState.Normal;
}
e.Handled = true;
}
private void OnEndFullScreenCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = this.WindowState == WindowState.Maximized && this.WindowStyle == WindowStyle.None;
}
private void OnEndFullScreenExecuted(object sender, ExecutedRoutedEventArgs e)
{
this.MediaElement.Stretch = this.stretch;
this.WindowStyle = WindowStyle.SingleBorderWindow;
this.SizeToContent = SizeToContent.WidthAndHeight;
this.WindowState = WindowState.Normal;
e.Handled = true;
}
}
Check out the demo project for more samples. Sample video from https://pixabay.com/