I recently had the need to change the state of a MediaElement to coincide with other page functionality. You can easily change the state of a MediaElement from the code-behind but you can’t unit test this. At first I thought, it would be easy to just bind the CurrentState property to a ViewModel property but this is a readonly property. I couldn’t find any way to bind/set the state from XAML, so here’s what I came up with.
I created a custom control that inherits from ContentControl, assumes the content is a MediaElement and has a MvvmMediaElementState property which sets the state on the content MediaElement. The MvvmMediaElementState property has a coinciding DependencyProperty to facilitate binding. Here is the code …
CustomControl:
public class MvvmMediaElementWrapper : ContentControl
{
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
“MvvmMediaElementState”,
typeof (MediaElementState),
typeof (MvvmMediaElementWrapper),
new PropertyMetadata(OnStateChanged));private static void OnStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var actions = new Dictionary<MediaElementState, Action<MediaElement>>
{
{MediaElementState.Playing, element =>
{
element.Position = TimeSpan.FromSeconds(0.0);
element.Play();
}},
{MediaElementState.Stopped, element => element.Stop()},
};var value = (MediaElementState)e.NewValue;
var mediaElement = (MediaElement) ((MvvmMediaElementWrapper) d).Content;
if (actions.ContainsKey(value))
actions[value](mediaElement);
}public MediaElementState MvvmMediaElementState
{
get
{
var state = _mediaElement.CurrentState;
SetValue(StateProperty, state);
return state;
}
set
{
SetValue(StateProperty, value);
}
}MediaElement _mediaElement
{
get
{
return (MediaElement)this.Content;
}
}
}
XAML:
<custom:MvvmMediaElementWrapper MvvmMediaElementState=”{Binding BackgroundMediaState, Mode=TwoWay}”>
<MediaElement Source=”test.wmv” AutoPlay=”False” Height=”860″ />
</custom:MvvmMediaElementWrapper>
I can now unit test when the MediaElement state should be changed and what it should be changed to in my ViewModel. This worked out be pretty nicely to me. Anyone have a better way?