Click here to Skip to main content
Click here to Skip to main content

A simple WPF media player with media item list

, 13 Sep 2007
Rate this:
Please Sign up or sign in to vote.
A simple WPF media player with media item list.

Contents

Introduction

I used a MediaElement some time ago in one my first WPF articles, and thought it may be time to re-visit it and make a simple video player control. That is what this article is all about really. There's nothing ground breaking here, as Josh Smith is the one to watch for amazing WPF tricks; he's crazy, man believe me, he know what's what in WPF. I am a mere underling, showing simpler subjects to beginners of WPF. So that's what we are going to do, build a simple media player control that will have the following features:

  • Play videos
  • Control media playback (pause / stop / play)
  • Control media volume
  • Control media position
  • Scale media
  • Rate each media item

So those were my basic ideas. What I will do is talk about each item in turn as the article progresses.

How it Works

OK, first of all, I will just mention what files are involved; these are as follows:

  • Resources/Styles.xaml: All the WPF Styles
  • Resources/Templates.xaml: All the WPF Templates
  • Utility Classes/GridLengthAnimation.cs: GridLength animator, by Christian Graus, Nishant Sivakumar, available here
  • Utility Classes/MediaItem.cs: A simple media item to be used to bind a ItemsControl (ListBox)
  • Utility Classes/XmlHandler.cs: A simple XML read/writer to load/save media item lists
  • ucMediaPlayer.xaml: The main media player control

That's it. Shall we carry on and see how each part was done? I won't explain it all as a lot of it is standard WPF stuff like Styles/Templates/Binding, but sometimes, there will even be something there that needs to be mentioned. So let's carry on, shall we?

Play Videos

As the WPF MediaElement relies on the Windows Media Player, I simply only allow files that are supported by the WMP to be played in the attached control. This is a fairly simple thing to do. I firstly allow the user to drag and drop files on to the control, and then check what type the files are. The associated code is shown below:

/// <summary>
/// Handles Drop Event for Media Items.
/// </summary>
private void Media_Drop(object sender, DragEventArgs e)
{
    string[] fileNames = e.Data.GetData(DataFormats.FileDrop, true) 
        as string[];
    //keep a dictionary of added files
    foreach (string f in fileNames)
    {
        if (IsValidMediaItem(f))
            mediaItems.Add(f.Substring(f.LastIndexOf(@"\")+1),
    new MediaItem(@f,0));
    }

    //now add to the list
    foreach (MediaItem mi in mediaItems.Values)
        lstMediaItems.Items.Add(mi);

    // Mark the event as handled,
    // so the control's native Drop handler is not called.
    e.Handled = true;
}

/// <summary>
/// check to see if dragged items are valid
/// </summary>
/// <returns>true if filename is valid</returns>
private bool IsValidMediaItem(string filename)
{
    bool isValid = false;
    string fileExtesion = filename.Substring(filename.LastIndexOf("."));
    foreach (string s in MediaItem.allowableMediaTypes)
    {
        if (s.Equals(fileExtesion, 
    StringComparison.CurrentCultureIgnoreCase))
            isValid = true;
    }
    return isValid;
}

That's all there is to that.

Control Media Playback (Pause / Stop / Play)

When dealing with the WPF MediaElement, you can either use Media StoryBoards or use code. To use code, you must ensure MediaElement.LoadedBehavior="Manual", and if you have that, it simply is a question of using the following methods on the MediaElement:

  • mediaPlayerMain.Play()
  • mediaPlayerMain.Pause()
  • mediaPlayerMain.Stop()

Control Media Volume

All I do here is use a Slider WPF control to alter the MediaElement's Volume property.

Control Media Position

All I do here is use a Slider WPF control to alter the MediaElement's Position property.

Scale Media

I wanted to be able to make the MediaElement take up the total available screen real estate. To this end, when you click on the main MediaElement, it will animate to take up the available screen area by hiding the media list. This uses the excellent article by Christian Graus, Nishant Sivakumar, which is available here.

Rate Each Media Item

I wanted to be able to rate the media items. So I created a special rating button Style which is applied to some ToggleButtons.

The Style code for this is as follows, where the stars are actually drawn using the Data property.

<!-- Rating Cell-->
<Style x:Key="StarToggleButton" TargetType="{x:Type ToggleButton}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type ToggleButton}">
          <Canvas Width="12" Height="12">
            <Path Name="star" Fill="Gray" 
        Data="M 5,0 L 4,4 L 0,4 L 3,7 L 2,11 L 5,9 L 6,9 L 9,11 L 8,
        7 L 11,4 L 7,4 L 6,0"/>
          </Canvas>
          <ControlTemplate.Triggers>
            <Trigger Property="IsChecked" Value="True">
              <Setter TargetName="star" Property="Fill" Value="Gold"/>
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
</Style>

This results in the following control:

Some Other Stuff

Some other nice bits are that I use some 3D buttons (taken straight out of Adam Nathan's WPF Unleashed book). As the 3D buttons are achieved by using a standard WPF style, they can also show content, as I do here where I have a video playing on the 3D buttons.

The style to do all this is shown below. But as I say, I stole this from Adam Nathan's WPF Unleashed book.

<!-- 3D Media Buttons -->
<Style x:Key="btn3DStyle"  TargetType="{x:Type Button}">
    <Style.Resources>
      <Storyboard x:Key="Spin">
        <DoubleAnimation
          Storyboard.TargetName="CubeRotation"
          Storyboard.TargetProperty="Angle" BeginTime="0:0:0"
          Duration="0:0:1" From="0" To="360" 
          DecelerationRatio="0.5" 
          AccelerationRatio="0.5" />
        <DoubleAnimation
          Storyboard.TargetName="CubeRotation"
          Storyboard.TargetProperty="Angle" BeginTime="0:0:1"
          Duration="0:0:1" From="360" 
          To="0" DecelerationRatio="0.5" 
          AccelerationRatio="0.5" />
        <DoubleAnimation
          Storyboard.TargetName="CubeScale"
          Storyboard.TargetProperty="ScaleX"
          BeginTime="0:0:0"
          Duration="0:0:1" From="0.5" To="0.75" />
        <DoubleAnimation
          Storyboard.TargetName="CubeScale"
          Storyboard.TargetProperty="ScaleX"
          BeginTime="0:0:1"
          Duration="0:0:1" From="0.75" To="1.0" />
        <DoubleAnimation
          Storyboard.TargetName="CubeScale"
          Storyboard.TargetProperty="ScaleY"
          BeginTime="0:0:0"
          Duration="0:0:1" From="0.5" To="0.75" />
        <DoubleAnimation
          Storyboard.TargetName="CubeScale"
          Storyboard.TargetProperty="ScaleY"
          BeginTime="0:0:1"
          Duration="0:0:1" From="0.75" To="1.0" />
        <DoubleAnimation
          Storyboard.TargetName="CubeScale"
          Storyboard.TargetProperty="ScaleZ"
          BeginTime="0:0:0"
          Duration="0:0:1" From="0.5" To="0.75" />
        <DoubleAnimation
          Storyboard.TargetName="CubeScale"
          Storyboard.TargetProperty="ScaleZ"
          BeginTime="0:0:1"
          Duration="0:0:1" From="0.75" To="1.0" />
      </Storyboard>
    </Style.Resources>

    <Setter Property="Width" Value="100"/>
    <Setter Property="Height" Value="100"/>    
    
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate>

          <ControlTemplate.Triggers>
            <Trigger Property="Button.IsMouseOver" Value="true">
              <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource Spin}"/>
              </Trigger.EnterActions>
            </Trigger>
          </ControlTemplate.Triggers>

          <Viewport3D>
            <Viewport3D.Camera>
              <PerspectiveCamera Position="4,4,4" LookDirection="-1,-1,-1" />
            </Viewport3D.Camera>
            <Viewport3D.Children>
              <ModelVisual3D>
                <ModelVisual3D.Content>
                  <DirectionalLight Direction="-0.3,-0.4,-0.5" />
                </ModelVisual3D.Content>
              </ModelVisual3D>
              <ModelVisual3D x:Name="Cube">
                <ModelVisual3D.Transform>

                  <Transform3DGroup>
                    <RotateTransform3D>
                      <RotateTransform3D.Rotation>
                        <AxisAngleRotation3D x:Name="CubeRotation" 
                          Axis="1,2,3" Angle="0" />
                      </RotateTransform3D.Rotation>
                    </RotateTransform3D>
                    <ScaleTransform3D x:Name="CubeScale" ScaleX="1" 
                      ScaleY="1" ScaleZ="1" CenterX="0" 
                      CenterY="0" CenterZ="0" />
                  </Transform3DGroup>

                </ModelVisual3D.Transform>
                <ModelVisual3D.Content>
                  <GeometryModel3D x:Name="OB_Cube">
                    <GeometryModel3D.Material>
                      <DiffuseMaterial>
                        <DiffuseMaterial.Brush>
                          <VisualBrush ViewportUnits="Absolute" Transform="1,0,0,-1,0,1">
                            <VisualBrush.Visual>
                              <Border 
                                   Background="{Binding Path=Background, 
                                     RelativeSource='{RelativeSource TemplatedParent}'}">
                                <Label Content="{Binding Path=Content, 
                                     RelativeSource='{RelativeSource TemplatedParent}'}" />
                              </Border>
                            </VisualBrush.Visual>
                          </VisualBrush>
                        </DiffuseMaterial.Brush>
                      </DiffuseMaterial>
                    </GeometryModel3D.Material>
                    <GeometryModel3D.Geometry>
                      <MeshGeometry3D x:Name="ME_Cube"
                        Positions="1,1,-1 1,-1,-1 -1,-1,-1 -1,1,-1 1,1,
                                   1 -1,1,1 -1,-1,1 1,-1,1 1,1,
                                   -1 1,1,1 1,-1,1 1,-1,-1 1,-1,-1 1,-1,1 -1,
                                   -1,1 -1,-1,-1 -1,-1,-1 -1,-1,1 -1,1,1 -1,1,
                                   -1 1,1,1 1,1,-1 -1,1,-1 -1,1,1"
                        TriangleIndices="0 1 2 0 2 3 4 5 6 4 6 7 8 9 10 8 
                                         10 11 12 13 14 12 14 15 16 17 
                                         18 16 18 19 20 21 22 20 22 23"
                        TextureCoordinates="0,1 0,0 1,0 1,1 1,1 -0,1 0,
                                            -0 1,0 1,1 -0,1 0,-0 1,0 1,0 1,
                                            1 -0,1 0,-0 -0,0 1,-0 1,1 0,
                                            1 1,-0 1,1 0,1 -0,0"/>
                    </GeometryModel3D.Geometry>
                  </GeometryModel3D>
                </ModelVisual3D.Content>
              </ModelVisual3D>
            </Viewport3D.Children>
          </Viewport3D>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
</Style>

I also apply some animations to rotate and size these buttons, nice huh? Oh, the media item styles can also be swapped to a more conventional button by using the last button in the media items area. In both the 3D buttons' and the standard buttons' cases, I also created a nicer tooltip.

How to Use it

It's pretty easy actually (I hope); either drag and drop some media items to the left hand side list box area, or load a previously saved XML media list. When the media items are loaded, just click one and it will start to play in the main window, where you may control it using the controls provided.

That's it

Although there is not that much code in this article, I had fun doing this one, and hope that it will be useful to someone out there.

So What Do You Think?

I would just like to ask, if you liked the article, please vote for it, and leave some comments, as it lets me know if the article was at the right level or not, and whether it contained what people need to know.

Conclusion

There is not too much to mention here as I think the rest of the article pretty much covers it.

History

  • v1.0 - 13/09/07: Initial issue.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
 
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
 
Both of these at Sussex University UK.
 
Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
QuestionOne short question PinmemberZhDima15-Sep-13 19:14 
AnswerRe: One short question PinmvpSacha Barber16-Sep-13 4:16 
QuestionMediaElement doesn't work on internet !!? PinmemberJohnson.Gao.12621-Aug-13 16:37 
QuestionMediaElement has a memory leak. don't use it PinmemberJason Jakob4-Jun-13 19:14 
AnswerRe: MediaElement has a memory leak. don't use it PinmemberJohnson.Gao.12621-Aug-13 16:39 
GeneralCapturing Video Pinmemberbl_miles24-Feb-11 6:09 
GeneralRe: Capturing Video PinmvpSacha Barber24-Feb-11 6:11 
GeneralMy vote of 5 PinmemberHessam Abbasi5-Jul-10 21:09 
GeneralNice article but.... PinmemberTamil Mannan23-Mar-10 2:27 
GeneralRe: Nice article but.... PinmvpSacha Barber23-Mar-10 2:35 
QuestionCool, but how to play the file on the network? Pinmembersmallrui27-Jan-10 16:36 
AnswerRe: Cool, but how to play the file on the network? Pinmembersmallrui27-Jan-10 16:59 
GeneralRe: Cool, but how to play the file on the network? PinmvpSacha Barber27-Jan-10 21:43 
GeneralRe: Cool, but how to play the file on the network? PinmvpSacha Barber27-Jan-10 21:44 
GeneralRe: Cool, but how to play the file on the network? Pinmembersmallrui31-Jan-10 22:28 
QuestionRe: Cool, but how to play the file on the network? PinmemberCristiDR5-May-10 0:56 
AnswerRe: Cool, but how to play the file on the network? PinmvpSacha Barber5-May-10 1:19 
QuestionWhat kind of license PinmemberKrzysiek.Staszak1-Jun-09 11:23 
AnswerRe: What kind of license PinmvpSacha Barber1-Jun-09 21:34 
GeneralAccess Violation Errors. PinmemberJammer27-May-09 11:18 
GeneralRe: Access Violation Errors. PinmvpSacha Barber27-May-09 23:37 
GeneralRe: Access Violation Errors. PinmemberJammer28-May-09 2:27 
GeneralRe: Access Violation Errors. PinmemberJason Jakob4-Jun-13 19:11 
GeneralNeed to play mov, mp4 and avi using MediaElement PinmemberMember 240988811-May-09 11:28 
GeneralRe: Need to play mov, mp4 and avi using MediaElement PinmvpSacha Barber12-May-09 23:01 
GeneralRe: Need to play mov, mp4 and avi using MediaElement PinmemberSangwookPark14-May-09 18:42 
GeneralRe: Need to play mov, mp4 and avi using MediaElement PinmvpSacha Barber14-May-09 21:43 
GeneralRe: Need to play mov, mp4 and avi using MediaElement Pinmembersoft2buy27-Sep-09 18:06 
QuestionCan We Replicate Windows Media Player's Behavior? Pinmemberrohan_puranik5-May-09 1:51 
AnswerRe: Can We Replicate Windows Media Player's Behavior? PinmvpSacha Barber12-May-09 23:00 
QuestionPlease Help !!!! PinmemberMen Bahalemeh3-May-09 3:52 
AnswerRe: Please Help !!!! Pinmembersoft2buy27-Sep-09 19:07 
Questionthis code is not working. What are the basic requirements to run this code? PinmemberBehlim25-Mar-09 6:00 
GeneralMedia Items added more than once PinmemberMember 374345325-Jan-09 8:49 
GeneralRe: Media Items added more than once PinmvpSacha Barber25-Jan-09 21:44 
GeneralRe: Media Items added more than once PinmemberMember 374345326-Jan-09 4:07 
GeneralRe: Media Items added more than once PinmvpSacha Barber26-Jan-09 4:47 
GeneralScreen Grab Pinmembercbm5-Jan-09 13:21 
GeneralRe: Screen Grab PinmvpSacha Barber5-Jan-09 21:53 
GeneralError when i load an XMl clear it and add it again. Pinmemberhisham2k74-Jan-09 19:25 
GeneralRe: Error when i load an XMl clear it and add it again. PinmemberBenetz19-Aug-09 22:22 
QuestionGreen pixels? Pinmemberhalexic15-Dec-08 3:36 
QuestionCool But ... Pinmemberh.jaza6-Dec-08 9:37 
AnswerRe: Cool But ... PinmvpSacha Barber6-Dec-08 21:20 
GeneralRe: Cool But ... Pinmemberh.jaza7-Dec-08 4:29 
GeneralRe: Cool But ... PinmemberJoe Conaty9-Mar-09 6:53 
QuestionOther video file formats?? PinmemberHunsoul5-Aug-08 6:51 
AnswerRe: Other video file formats?? PinmvpSacha Barber6-Aug-08 3:46 
GeneralRe: Other video file formats?? PinmemberHunsoul6-Aug-08 22:59 
GeneralRe: Other video file formats?? PinmemberHunsoul22-Aug-08 3:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140718.1 | Last Updated 13 Sep 2007
Article Copyright 2007 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid