Information
I have a Multiscreen Application written for a Client that basically is displaying Video content with MediaElements bind to a ContentControl on 5 Screens horizontally(5 splittet Videos). Depending on wich view the User is im playing different 5 Videos and Stopping the Other Videos.
I've put the MediaElements in a library and at App Start I'm loading the 5x5 Videos with 1920x1080(mp4). The App runs ok but I'm not happy with my Code, and I have the feeling that this could be done much better and I always keep questioning myself because of my Code.
Since I'm working alone and I don't know other Devs I would love to hear criticism about my Code because I want to learn to get better
The Code
public class VideoWallViewModel : BindableBase {
public VideoWallViewModel() {
Initialize();
}
#region Functions
private void Initialize() {
_iEventAggregator = Event.EventInstance.EventAggregator;
MediaElement0 = new MediaElement();
MediaElement1 = new MediaElement();
MediaElement2 = new MediaElement();
MediaElement3 = new MediaElement();
MediaElement4 = new MediaElement();
MediaElement0.BeginInit();
MediaElement1.BeginInit();
MediaElement2.BeginInit();
MediaElement3.BeginInit();
MediaElement4.BeginInit();
MediaElement0.LoadedBehavior = MediaState.Manual;
MediaElement1.LoadedBehavior = MediaState.Manual;
MediaElement2.LoadedBehavior = MediaState.Manual;
MediaElement3.LoadedBehavior = MediaState.Manual;
MediaElement4.LoadedBehavior = MediaState.Manual;
MediaElement0.Loaded += MediaElementOnLoaded;
MediaElement1.Loaded += MediaElementOnLoaded;
MediaElement2.Loaded += MediaElementOnLoaded;
MediaElement3.Loaded += MediaElementOnLoaded;
MediaElement4.Loaded += MediaElementOnLoaded;
MediaElement0.MediaOpened += MediaElementOnMediaOpened;
MediaElement1.MediaOpened += MediaElementOnMediaOpened;
MediaElement2.MediaOpened += MediaElementOnMediaOpened;
MediaElement3.MediaOpened += MediaElementOnMediaOpened;
MediaElement4.MediaOpened += MediaElementOnMediaOpened;
MediaElement0.MediaEnded += MediaElementOnMediaEnded;
MediaElement1.MediaEnded += MediaElementOnMediaEnded;
MediaElement2.MediaEnded += MediaElementOnMediaEnded;
MediaElement3.MediaEnded += MediaElementOnMediaEnded;
MediaElement4.MediaEnded += MediaElementOnMediaEnded;
MediaElement0.MediaFailed += MediaElement0OnMediaFailed;
MediaElement1.MediaFailed += MediaElement0OnMediaFailed;
MediaElement2.MediaFailed += MediaElement0OnMediaFailed;
MediaElement3.MediaFailed += MediaElement0OnMediaFailed;
MediaElement4.MediaFailed += MediaElement0OnMediaFailed;
MediaElement0.EndInit();
MediaElement1.EndInit();
MediaElement2.EndInit();
MediaElement3.EndInit();
MediaElement4.EndInit();
MediaElement0.Volume = 0;
MediaElement1.Volume = 0;
MediaElement2.Volume = 0;
MediaElement3.Volume = 0;
MediaElement4.Volume = 0;
OutroTimer = new DispatcherTimer{
Interval = new TimeSpan(0, 0, 0, 60)
};
OutroTimer.Tick += DispatcherTimerOnTick;
}
private static void MediaElement0OnMediaFailed(object sender, ExceptionRoutedEventArgs exceptionRoutedEventArgs) {
var errorException = exceptionRoutedEventArgs.ErrorException;
var media = exceptionRoutedEventArgs.Source as MediaElement;
MessageBox.Show($"Screen:\n{media?.Source}\nException:\n{errorException.StackTrace}", "Media Failed",
MessageBoxButton.OK, MessageBoxImage.Error);
}
private void DispatcherTimerOnTick(object sender, EventArgs eventArgs) {
State = State.Stop;
OutroTimer.Stop();
TimerCompletedEventHandler?.Invoke();
}
private void ApplyState() {
switch (State) {
case State.Stop:
Stop();
Visibility = Visibility.Hidden;
break;
case State.Play:
Play();
Visibility = Visibility.Visible;
break;
case State.Pause:
Pause();
Visibility = Visibility.Visible;
break;
case State.None:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void MediaChanged(VideoWallMedia media) {
MediaElement0.Source = media.Video0;
MediaElement1.Source = media.Video1;
MediaElement2.Source = media.Video2;
MediaElement3.Source = media.Video3;
MediaElement4.Source = media.Video4;
switch (State) {
case State.Stop:
Stop();
break;
case State.Play:
Play();
break;
case State.Pause:
Pause();
break;
case State.None:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private static void MediaElementOnLoaded(object sender, RoutedEventArgs routedEventArgs) {
var mediaElement = sender as MediaElement;
mediaElement?.Stop();
}
private void MediaElementOnMediaEnded(object sender, RoutedEventArgs routedEventArgs) {
var mediaElement = sender as MediaElement;
if (StopAtLastFrame) {
mediaElement.Position = new TimeSpan(12);
mediaElement.Pause();
if (!OutroTimer.IsEnabled) {
OutroTimer.Start();
}
if (!fired) {
_iEventAggregator.GetEvent<PubSubEvent>().Publish();
fired = true;
}
}
else {
if (Loop) {
mediaElement?.Stop();
mediaElement?.Play();
}
else {
State = State.Stop;
_iEventAggregator.GetEvent<PubSubEvent>().Publish();
}
}
}
private void MediaElementOnMediaOpened(object sender, RoutedEventArgs routedEventArgs) {
var mediaElement = sender as MediaElement;
if (mediaElement == null) {
return;
}
_loadedMediaElements.Add(mediaElement);
if (_loadedMediaElements.Count != 5 || State != State.Play) {
return;
}
foreach (var element in _loadedMediaElements) {
element.Play();
}
_loadedMediaElements = new List<MediaElement>();
}
private void Pause() {
MediaElement0.Pause();
MediaElement1.Pause();
MediaElement2.Pause();
MediaElement3.Pause();
MediaElement4.Pause();
}
private void Play() {
MediaElement0.Play();
MediaElement1.Play();
MediaElement2.Play();
MediaElement3.Play();
MediaElement4.Play();
}
private void Stop() {
MediaElement0.Stop();
MediaElement1.Stop();
MediaElement2.Stop();
MediaElement3.Stop();
MediaElement4.Stop();
}
#endregion