// MediaButton.cs using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Navigation; namespace CustomWPF { public enum IconType { Play, Pause } public class MediaButton : Control { static MediaButton() { //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. //This style is defined in themes\generic.xaml DefaultStyleKeyProperty.OverrideMetadata(typeof(MediaButton), new FrameworkPropertyMetadata(typeof(MediaButton))); } #region Fields RoutedEventHandler _mediaEndedHandler; #endregion // Fields #region Dependency Properties #region Icon Property /// /// The Dependency Property for the /// Icon property. /// public static readonly DependencyProperty IconProperty = DependencyProperty.Register( "Icon", typeof(IconType), typeof(MediaButton), new PropertyMetadata(IconType.Play)); /// /// The Outline Icon used for the /// MediaButton control. /// public IconType Icon { get { return (IconType)GetValue(IconProperty); } set { SetValue(IconProperty, value); } } #endregion // Icon Property #region MediaPlayer Property /// /// The Dependency Property for the /// MediaPlayer property. /// public static readonly DependencyProperty MediaPlayerProperty = DependencyProperty.Register( "MediaPlayer", typeof(MediaElement), typeof(MediaButton), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnMediaPlayerChanged))); /// /// The ID of the Media Element that the button is tied to. /// public MediaElement MediaPlayer { get { return (MediaElement)GetValue(MediaPlayerProperty); } set { SetValue(MediaPlayerProperty, value); } } /// /// Static Event that is called when the property is changed. /// /// The object that has changed. /// The arguments to the property. private static void OnMediaPlayerChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { MediaButton control = (MediaButton)obj; control.UpdateMediaPlayer(args.OldValue as MediaElement, args.NewValue as MediaElement); } #endregion // MediaPlayer Property #endregion Dependency Properties #region Events #region Clicked Event public static readonly RoutedEvent ClickedEvent = EventManager.RegisterRoutedEvent("Clicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MediaButton)); public event RoutedEventHandler Clicked { add { AddHandler(ClickedEvent, value); } remove { RemoveHandler(ClickedEvent, value); } } void RaiseClickEvent() { RoutedEventArgs newEventArgs = new RoutedEventArgs(MediaButton.ClickedEvent, this); RaiseEvent(newEventArgs); } protected virtual void OnClick() { RaiseClickEvent(); } #endregion #endregion #region Event Handlers /// /// Event Handler for when the Media Player has ended /// the media file. /// /// The Media Player /// The handler void Media_MediaEnded(object sender, RoutedEventArgs e) { MediaPlayer.Stop(); Icon = IconType.Play; } protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { base.OnMouseLeftButtonUp(e); // Determine the right course of action if (MediaPlayer != null) { switch (Icon) { case IconType.Play: { Icon = IconType.Pause; MediaPlayer.Play(); break; } case IconType.Pause: { Icon = IconType.Play; MediaPlayer.Pause(); break; } default: { throw new InvalidOperationException("Unexpected IconType detected in MediaButton"); } } } // Raise the event to the users RaiseClickEvent(); } #endregion // Event Handlers #region Methods /// /// Used to register and unregister from MediaElements that the control are tied to. /// /// The Media Element (if any) to unregister event notification. /// The Media ELement on which to register event notification. void UpdateMediaPlayer(MediaElement oldMedia, MediaElement newMedia) { if (newMedia.LoadedBehavior != MediaState.Manual) { throw new NotSupportedException("Media Element's LoadedBehavior must be set to Manual to use this MediaButton"); } // Unregister if necessary if (_mediaEndedHandler != null && oldMedia != null) { oldMedia.MediaEnded -= _mediaEndedHandler; } // Register for the event if (newMedia != null) { // Create the handler if necessary if (_mediaEndedHandler == null) { _mediaEndedHandler = new RoutedEventHandler(Media_MediaEnded); } // Register for the Event newMedia.MediaEnded += _mediaEndedHandler; } } #endregion // Methods } }