Amazon.com Widgets Using Expression Encoder 2 Silverlight 2 Templates in your project

WilliaBlog.Net

I dream in code

About the author

Robert Williams is an internet application developer for the Salem Web Network.
E-mail me Send mail
Code Project Associate Logo
Go Daddy Deal of the Week: 30% off your order at GoDaddy.com! Offer expires 11/6/12

Recent comments

Archive

Authors

Tags

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.


Using Expression Encoder 2 Silverlight 2 Templates in your project

Some time ago, I wrote a popular article on how to create a scrolling Silverlight 1.x Playlist using Microsoft Expression Encoder output. Well, I finally found some time to revisit that application to see how I might upgrade it to Silverlight 2. As you are probably aware, Expression Encoder 2 Service Pack 1 is now out and it ships with a handful of Player templates just for Silverlight 2. Among these new templates are two which already have built in Scrolling playlists and I thought I would test one out.

However, I already have all my videos encoded - including all the chapter point thumbnails, etc. so I didn't want to start inside Encoder, have it build my project and work from there like I did last time. This time, I created a new Silverlight 2.0 Usercontrol project in Visual Studio 2008 and worked for a week or two on the new look and feel for the site before I decided it was time to merge my project with the Expression Encoder template. I found Tim Heuer's blog entry on integrating these new templates very helpful, though I feel it is important to add that the template itself, meaning the look and feel of the player, is not stored in the dlls and it does not matter which of the template projects you open and compile, just referencing the dlls and following Tim's instructions will always give you the standard Silverlight 2 player. In order to add the look and feel you must copy (or merge) the contents of the Page.xaml file in that template into your own UserControl.

For my project I wanted the player to be a seperate UserControl, so I went to Project > New Item >  Silverlight User Control, and called it MediPlayer.xaml. Next I pasted everything from C:\Program Files\Microsoft Expression\Encoder 2\Templates\en\FrostedGallery\Source\Page.xaml into my new MediaPlayer.xaml file, then changed the x:Class at the very top to reflect my original NameSpace and Class Name. (If you forget what it was, just undo your paste, make a note of it and redo the paste).

I also wanted my Player control to be available on multiple pages, and I wanted it hidden most of the time, only to pop up in a pseudo modal 'Lightbox' format with a close button. To achieve this effect I simply used these techniques described by Scot Guthrie in his excellent tutorial on creating a Silverlight Digg application. So now I had my player, and I could show and hide it with the click of a button. Basically, my site showcases the James Bond Movies, and I have customized the Yet Another Carousel control so that you can click on the selected box art and read the synopsis, watch the Trailer and buy it on Amazon.com. My initial idea therefore, was to create a new PlayListItem programatically and add it to the player's PlayListCollection in the onLeftMouseButtonUp event of the button. What I found was that while this worked quite nicely, I ultimately ended up with a playlist slowly being generated by the user in the order in which the user clicked on the movies, making it harder to keep track of which item in the collection was which movie, but more importantly I couldn't figure out how to take full advantage of all the chapter information and thumbnails I had created for the original project. I could create chapter item objects, and add them to my own PlayListCollection object, but I could not bind that new object to my player since the Playlist Property is read only.

Reading more of Tim's blog I saw that you could add some xml to the InitParams of the control, but I have 24 videos, each with thumbnail paths for at least 4 chapter points and I didn't need to start typing that all into a single line to understand what a nightmare that would become: not only would it be hard to read and maintain but also it goes against the whole MVC seperation of code, data and presentation layers, ethic we have all grown so attached to.

More google searches led me to this solution which does allow you to move the creation of the parameters into the code behind, but seems to require tinkering with the original template code, which I am not opposed to, but I'd already thought of a cleaner solution. What I wanted was a way to create an xml file containing my entire playlist in this format:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <playList>
   3:   <playListItems>
   4:     <playListItem title="Dr No" description="Trailer" mediaSource="ClientBin/01_dr_no.wmv" adaptiveStreaming="False" thumbSource="ClientBin/01_dr_no_Thumb.jpg" >
   5:       <chapters>
   6:         <chapter  position="29.176" thumbnailSource="ClientBin/01_dr_no_MarkerThumb 00.00.29.1760677.jpg" title="1" />
   7:         <chapter  position="49.374" thumbnailSource="ClientBin/01_dr_no_MarkerThumb 00.00.49.3748838.jpg" title="2" />
   8:         <!-- etc -->
  20:       </chapters>
  21:     </playListItem>
  22:   </playListItems>
  23: </playList>

and simply pass the file to my player. And my Solution turned out to be trivially easy: I created a new class that inherits from ExpressionMediaPlayer.MediaPlayer, and added a new method that would accept my file:

 

using System;

using System.Diagnostics;

using System.Net;

using System.Windows;

using System.Windows.Browser;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Ink;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using System.Xml.Linq;

 

 

namespace Bond_Silverlight2

{

    public class MI6MediaPlayer : ExpressionMediaPlayer.MediaPlayer

    {

        public MI6MediaPlayer(): base()

        {

        }

 

        public void OnStartup(string xmlPlayList)

        {

            XDocument document = XDocument.Load(xmlPlayList);

            try

            {

                Playlist.Clear();

                Playlist.ParseXml(HtmlPage.Document.DocumentUri, document.ToString());

            }

            catch (System.Xml.XmlException xe)

            {

                Debug.WriteLine("XML Parsing Error:" + xe.ToString());

            }

            catch (NullReferenceException)

            {

            }

        }

 

    }

}

 


This required some minor changes to the MediaPlayer.xaml file, inorder to make it use my version of the player:

First of all, I replaced the <expression:ExpressionPlayer> tags with <Bond_Silverlight2:MI6MediaPlayer> tags and any static resource styles that had a target type of ExpressionPlayer:ExpressionPlayer also needed to be replaced, and then everything used my new player. Obviously, there was another step - how to initialize and pass my xml playlist to my new player. First, I created my xml file in the format outlined above. It is important to note, that my video files and associated JPEG files are stored on the webserver inside the Clientbin folder, rather than inside the xap file as resources or content. In the code behind of my MediaPlayer.xaml (that is the usercontrol I pasted the page.xaml into earlier, not the MI6MediaPlayer class from the code above), I call the startup method using a link to my xml file:

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

 

namespace Bond_Silverlight2

{

    public partial class MediaPlayer : UserControl

    {

        public MediaPlayer()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MediaPlayer_Loaded);

        }

 

        void MediaPlayer_Loaded(object sender, RoutedEventArgs e)

        {

            Player1.OnStartup("Playlist.xml");

        }

 

        private void Button_Click(object sender, RoutedEventArgs e)

        {

            Player1.Stop();

            Visibility = System.Windows.Visibility.Collapsed;

        }

    }

}

 

The xml file ("Playlist.xml") is stored as Content within the xap file. This should be the default behavior if you created the xml file inside Visual Studio by using the Project > Add Item menu, but if you didn't, you can check by right clicking on the xml file, choosing Properties and checking that the Build Action is "Content", and Copy to Output Directory is set to "Do Not Copy".

Now when my Player is first loaded into memory, my full playlist is immediately available.

 


Posted by Williarob on Wednesday, April 08, 2009 1:47 PM
Permalink | Comments (0) | Post RSSRSS comment feed
blog comments powered by Disqus