Ary Borenszweig

Ary Borenszweig

Embedding YouTube videos in Silverlight

8 min
Sep 11 2008
coding
8 min
Sep 11 2008

There's no straight way of embedding YouTube videos in Silverlight. What you can do, however, is to create a floating div over the Silverlight plugin, whose content will be the YouTube video control. For this purpose, I wrote a simple class to make it easier to do this.

The usage is simple:

// ZCcedd9EfHI is the id of the video to show
YouTubePlayer player = new YouTubePlayer("ZCcedd9EfHI")
{
    Top = 100,
    Left = 200,
    Width = 400,
    Height = 400
};

player.Embed();

// And, once you want to remove the video from the page...
player.Dispose();

That's it. Of course, you'll have to compute the Top, Left, Width and Height values if you want to center the video inside a particular Silverlight control. You can do this computation in the Loaded event of that control.

And the best thing is, you can save a reference to the YouTubePlayer instance and, in case the Silverlight plugin is resized or moved, changing the Top, Left, Width and Height properties will automatically execute javascript code to move/resize the player.

Here’s the full code in case someone finds it useful.

using System;
using System.Net;
using System.Windows;
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.Windows.Browser;

namespace Manas.Silverlight
{
    /// <summary>
    /// Allows embedding a YouTube player inside a Silveright application.
    ///
    /// Invoking the Embed() method of an instance of this class simply creates
    /// a floating div which contains an embedded YouTube flash player. For this
    /// reason, the Top and Left properties are absolute, and not relative to
    /// some particular Silverlight control.
    ///
    /// The Dispose() method removes the div from the page.
    ///
    /// Changing any dimension property of a player when it has already been embeded
    /// updates the div properties to reflect the changes.
    /// </summary>
    public class YouTubePlayer : IDisposable
    {

        /// <summary>
        /// The default with of a player, if none is specified.
        /// </summary>
        public const int DefaultWidth = 425;

        /// <summary>
        /// The default height of a player, if none is specified.
        /// </summary>
        public const int DefaultHeight = 344;

        #region Private properties
        private string uniqueId = Guid.NewGuid().ToString();

        private double top;
        private double left;
        private double height = DefaultHeight;
        private double width = DefaultWidth;

        private string videoId;
        private bool isEmbeded;
        private HtmlElement div;
        #endregion

        /// <summary>
        /// Creates a player for the given video id. You must invoke Embed()
        /// later, to actually insert the video into the page.
        /// </summary>
        /// <param name="videoId"></param>
        public YouTubePlayer(string videoId)
        {
            this.videoId = videoId;
        }

        /// <summary>
        /// The absolute y position of this player.
        /// </summary>
        public double Top
        {
            get { return top; }
            set
            {
                top = value;

                if (isEmbeded)
                {
                    SetStyleProperty(DivId, "top", """ + (int)top + "px"");
                }
            }
        }

        /// <summary>
        /// The absolute x position of this player.
        /// </summary>
        public double Left
        {
            get { return left; }
            set
            {
                left = value;

                if (isEmbeded)
                {
                    SetStyleProperty(DivId, "left", """ + (int)left + "px"");
                }
            }
        }

        /// <summary>
        /// The height of this player.
        /// </summary>
        public double Height
        {
            get { return height; }
            set
            {
                height = value;

                if (isEmbeded)
                {
                    SetAllDivsProperty("height", """ + (int)height + "px"");
                }
            }
        }

        /// <summary>
        /// The width of this player.
        /// </summary>
        public double Width
        {
            get { return width; }
            set
            {
                width = value;

                if (isEmbeded)
                {
                    SetAllDivsProperty("width", """ + (int)width + "px"");
                }
            }
        }

        /// <summary>
        /// Allow fullscreen to be activated?
        /// </summary>
        public bool AllowFullScreen { get; set; }

        /// <summary>
        /// Embeds this player into the HTML page. Invoking this method many
        /// times has no effect. You must invoke Dipose() to remove the player
        /// form the HTML page.
        /// </summary>
        public void Embed()
        {
            if (isEmbeded) return;
            isEmbeded = true;

            div = HtmlPage.Document.CreateElement("div");
            div.SetAttribute("id", DivId);
            div.SetAttribute("style", "position: absolute; width:" + (int)Width + "px; height:" + (int)Height + "px; top: " + (int)Top + "px; left: " + (int)Left + "px; z-index:10");
            div.SetProperty("innerHTML",
                "<object width="" + (int)Width + "" height="" + (int)Height + "" id="" + ObjectId + "">" +
                    "<param name="movie" value="http://www.youtube.com/v/" + videoId + "&hl=en&fs=1"></param>" +
                    "<param name="allowFullScreen" value="" + AllowFullScreen + ""></param>" +
                    "<embed id="" + EmbedId + "" src="http://www.youtube.com/v/" + videoId + "&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="" + AllowFullScreen + "" width="" + (int)Width + "" height="" + (int)Height + ""></embed>" +
                "</object>"
                );

            HtmlPage.Document.Body.AppendChild(div);
        }

        /// <summary>
        /// Removes this embedded player from the HTML page. Has no effect if this
        /// player was not embedded, or is already disposed.
        /// </summary>
        public void Dispose()
        {
            if (!isEmbeded) return;
            isEmbeded = false;

            HtmlPage.Document.Body.RemoveChild(div);
        }

        #region Implementation

        private string DivId { get { return "YouTubePlayer" + uniqueId; } }

        private string ObjectId { get { return "YouTubePlayer_Object_" + uniqueId; } }

        private string EmbedId { get { return "YouTubePlayer_Embed_" + uniqueId; } }

        private void SetAllDivsProperty(string property, object value)
        {
            SetProperty(DivId, property, value);
            SetProperty(ObjectId, property, value);
            SetProperty(EmbedId, property, value);
        }

        private void SetProperty(string divId, string property, object value)
        {
            HtmlPage.Window.Eval("document.getElementById("" + divId + "")." + property + " = " + value + ";");
        }

        private void SetStyleProperty(string divId, string property, object value)
        {
            HtmlPage.Window.Eval("document.getElementById("" + divId + "").style." + property + " = " + value + ";");
        }

        #endregion
    }
}