<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Grant Archibald</title>
    <link>http://www.garchibald.com/blog/</link>
    <description>Continuous Improvement</description>
    <language>en-us</language>
    <copyright>Grant Archibald</copyright>
    <lastBuildDate>Mon, 23 Feb 2009 13:09:47 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.1.8102.813</generator>
    <managingEditor>http://kontactr.com/user/garchibald</managingEditor>
    <webMaster>http://kontactr.com/user/garchibald</webMaster>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/grantarchibald" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=cf584be9-7fa0-4489-89b2-406200309688</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,cf584be9-7fa0-4489-89b2-406200309688.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,cf584be9-7fa0-4489-89b2-406200309688.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cf584be9-7fa0-4489-89b2-406200309688</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Keeping with the MIX09 contests theme, I have submitted an entry for Adam Kinney’s <a href="http://adamkinney.com/blog/411/default.aspx">Tell
a Fairy tale in Silverlight or WPF and win a FREE PASS TO MIX</a>.
</p>
        <p>
The interactive Silverlight e-book version of the Three Little Pigs is available from
my site on <a title="http://www.garchibald.com/ebooks/The-Three-Little-Pigs/" href="http://www.garchibald.com/ebooks/The-Three-Little-Pigs/">http://www.garchibald.com/ebooks/The-Three-Little-Pigs/</a><br /><br />
The e-book make use of:
</p>
        <ul>
          <li>
Page flip animations to navigate the pages.</li>
          <li>
Text to speech to read the story.</li>
          <li>
JavaScript to ensure that pages can be bookmarked. 
</li>
        </ul>
        <p>
If the user does not have Silverlight installed a HTML description is rendered and
a brief demonstration video is available to show the user what is available.
</p>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=cf584be9-7fa0-4489-89b2-406200309688" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/Z8JgN1pUAfs" height="1" width="1" /></body>
      <title>Three Little Pigs – Silverlight E-Book</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,cf584be9-7fa0-4489-89b2-406200309688.aspx</guid>
      <link>http://www.garchibald.com/blog/2009/02/23/ThreeLittlePigsSilverlightEBook.aspx</link>
      <pubDate>Mon, 23 Feb 2009 13:09:47 GMT</pubDate>
      <description>&lt;p&gt;
Keeping with the MIX09 contests theme, I have submitted an entry for Adam Kinney’s &lt;a href="http://adamkinney.com/blog/411/default.aspx"&gt;Tell
a Fairy tale in Silverlight or WPF and win a FREE PASS TO MIX&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
The interactive Silverlight e-book version of the Three Little Pigs is available from
my site on &lt;a title="http://www.garchibald.com/ebooks/The-Three-Little-Pigs/" href="http://www.garchibald.com/ebooks/The-Three-Little-Pigs/"&gt;http://www.garchibald.com/ebooks/The-Three-Little-Pigs/&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
The e-book make use of:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Page flip animations to navigate the pages.&lt;/li&gt;
&lt;li&gt;
Text to speech to read the story.&lt;/li&gt;
&lt;li&gt;
JavaScript to ensure that pages can be bookmarked. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
If the user does not have Silverlight installed a HTML description is rendered and
a brief demonstration video is available to show the user what is available.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=cf584be9-7fa0-4489-89b2-406200309688" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,cf584be9-7fa0-4489-89b2-406200309688.aspx</comments>
      <category>mix09</category>
      <category>silverlight</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=d3febb59-26c6-408c-8986-77b9a496bca6</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,d3febb59-26c6-408c-8986-77b9a496bca6.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,d3febb59-26c6-408c-8986-77b9a496bca6.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d3febb59-26c6-408c-8986-77b9a496bca6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In this post I will cover the changes required to use a PasswordBox control to display
the FTP password. 
</p>
        <p>
The following links a quick reference to the topics covered:
</p>
        <ul>
          <li>
            <a href="#FTPPluginOverview">FTP Plug-in Overview</a> – Quick description of the plug-in
control created by Tim Heuer. 
</li>
          <li>
            <a href="#FTPPluginChanges">FTP Plug-in Changes</a> – Steps to change the plug-in
to use a PasswordBox control instead of TextBox. 
</li>
          <li>
            <a href="#TestingTheChanges">Testing The Changes</a> – Describes testing the changes
with Expression Encoder and the issues encountered. 
</li>
          <li>
            <a href="#PasswordBoxStyles">PasswordBox Styles</a> – Describes to changes made to
alter the style for the PasswordBox control so that it has consistent look and feel. 
</li>
          <li>
            <a href="#InvestigatingDefaultStyles">Investigating Default Styles</a> - Investigating
the Expression Encoder WPF Styles using Redgate’s .Net Reflector. 
</li>
          <li>
            <a href="#FinalVersion">Final Version</a> – Describes the final version incorporating
the style changes in the previous sections. 
</li>
          <li>
            <a href="#Review">Review</a> – Describes the step taken to modify the plug-in to make
use the of a PasswordBox control.</li>
        </ul>
        <p>
Technologies Used
</p>
        <ul>
          <li>
Microsoft Visual Studio 2008 (with .Net 3.5 SP1 <a href="http://www.microsoft.com/net/">installed</a>) 
</li>
          <li>
Microsoft Expression Encoder 2 (with Expression Encoder 2 SP1 <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A29BE9F9-29E1-4E70-BF67-02D87D3E556E&amp;displaylang=en">installed</a>)</li>
        </ul>
        <h2>
          <a name="FTPPluginOverview">FTP Plug-in Overview</a>
        </h2>
        <p>
The <a href="http://www.codeplex.com/encoderftppublish">FTP Publishing Plug-in for
Encoder</a> created by <a href="http://timheuer.com/blog/">Tim Heuer</a> allows the
encoded output of to be “published” to a FTP server for hosting. One minor issue from
a security point of view is the password is shown in clear text. As a result the password
is always visible and it could represent a security risk.
</p>
        <p>
          <img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/ClearTextPassword.jpg" />
        </p>
        <p>
        </p>
        <p>
In the next section I will look at replacing the standard WPF text TextBox control
with a PasswordBox so that the password is masked from the user.
</p>
        <h2>
          <a name="FTPPluginChanges">FTP Plug-in Changes</a>
        </h2>
        <p>
Looking at the original XAML it is a standard TextBox that makes use of data binding
to load and save changes. 
</p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2ec36460-addf-430b-b968-e1738ba932c5" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">&lt;Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,3,0" Content="Password" /&gt;
&lt;TextBox Name="Password" Grid.Row="2" Grid.Column="1" ToolTip="FTP account password" Margin="0,2.5,0,2.5" Text="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&gt;</pre>
        </div>
        <p>
The obvious change to replace this with a PasswordBox and bind to the Password property
instead of the Text property. 
</p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8a02ca6c-3e70-46b5-b18b-7f0436fab20e" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">        &lt;Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,3,0" Content="Password" /&gt;
        &lt;PasswordBox  Name="Password" Grid.Row="2" Grid.Column="1" ToolTip="FTP account password" Margin="0,2.5,0,2.5" Password="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&gt;
</pre>
        </div>
        <p>
This however generates an error. Looking at the problem further, Samuel Jack provides
the explanation in his post <a href="http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html">WPF
PasswordBox and Data binding</a>. In the post he discusses how the Password property
is a plain CLR property rather than a <a href="http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty.aspx">Dependency
Property</a>, so it doesn't support being the target of a data binding. Using Samuel’s
solution the code is easily modified to make use of attached properties by adding
a attribute namespace reference at the top of the UserControl
</p>
        <p>
        </p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8024c6c1-d5ce-4041-9068-6300866da537" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">xmlns:FtpPublish="clr-namespace:TimHeuer.Expression.FtpPublish"</pre>
        </div>
        <p>
Combined with additions to the the PasswordBox xaml to make use of the attached properties
</p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f9cc00bc-34e8-4cc9-8317-a374cd81e711" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">&lt;Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,3,0" Content="Password" /&gt;
&lt;PasswordBox  Name="Password" Grid.Row="2" Grid.Column="1" ToolTip="FTP account password" Margin="0,2.5,0,2.5" FtpPublish:PasswordBoxAssistant.BindPassword="true" FtpPublish:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&gt;</pre>
        </div>
        <p>
        </p>
        <p>
And adding the following C# class to define the implementation of the PasswordBoxAssistant
class.
</p>
        <p>
        </p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b930a322-c7bb-4a2f-94b6-5952825c049e" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">using System.Windows;
using System.Windows.Controls;

namespace TimHeuer.Expression.FtpPublish
{
    /// &lt;summary&gt;
    /// Class that allows a &lt;see cref="PasswordBox"/&gt; to be included in DataBinding using attached properties
    /// &lt;/summary&gt;
    /// &lt;remarks&gt;
    /// Original source http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html
    /// &lt;/remarks&gt;
    public static class PasswordBoxAssistant
    {
        public static readonly DependencyProperty BoundPassword =
            DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));

        public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
            "BindPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));

        private static readonly DependencyProperty UpdatingPassword =
            DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant));

        private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var box = d as PasswordBox;

            // only handle this event when the property is attached to a PasswordBox
            // and when the BindPassword attached property has been set to true
            if (box == null || !GetBindPassword(d))
            {
                return;
            }

            // avoid recursive updating by ignoring the box's changed event
            box.PasswordChanged -= HandlePasswordChanged;

            var newPassword = (string)e.NewValue;

            if (!GetUpdatingPassword(box))
            {
                box.Password = newPassword;
            }

            box.PasswordChanged += HandlePasswordChanged;
        }

        private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
        {
            // when the BindPassword attached property is set on a PasswordBox,
            // start listening to its PasswordChanged event

            var box = dp as PasswordBox;

            if (box == null)
            {
                return;
            }

            var wasBound = (bool)(e.OldValue);
            var needToBind = (bool)(e.NewValue);

            if (wasBound)
            {
                box.PasswordChanged -= HandlePasswordChanged;
            }

            if (needToBind)
            {
                box.PasswordChanged += HandlePasswordChanged;
            }
        }

        private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
        {
            var box = sender as PasswordBox;

            if (box == null)
                return;

            // set a flag to indicate that we're updating the password
            SetUpdatingPassword(box, true);
            // push the new password into the BoundPassword property
            SetBoundPassword(box, box.Password);
            SetUpdatingPassword(box, false);
        }

        public static void SetBindPassword(DependencyObject dp, bool value)
        {
            dp.SetValue(BindPassword, value);
        }

        public static bool GetBindPassword(DependencyObject dp)
        {
            return (bool)dp.GetValue(BindPassword);
        }

        public static string GetBoundPassword(DependencyObject dp)
        {
            return (string)dp.GetValue(BoundPassword);
        }

        public static void SetBoundPassword(DependencyObject dp, string value)
        {
            dp.SetValue(BoundPassword, value);
        }

        private static bool GetUpdatingPassword(DependencyObject dp)
        {
            return (bool)dp.GetValue(UpdatingPassword);
        }

        private static void SetUpdatingPassword(DependencyObject dp, bool value)
        {
            dp.SetValue(UpdatingPassword, value);
        }
    }
}
</pre>
        </div>
        <h2>
          <a name="TestingTheChanges">Testing The Changes</a>
        </h2>
        <p>
Copying the updated dll to the &lt;Program Files&gt;\Microsoft Expression\Encoder
2\Plugins folder, the plug-in now correctly loads but the password box does not have
the correct visual styles applied to it because the PasswordBox has not been included
in the template styles for the WPF plug-in.
</p>
        <p>
          <img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/ChangedPasswordBoxNoStyle.jpg" />
        </p>
        <p>
Overall the control is missing the following functionality:
</p>
        <ul>
          <li>
The correct background colour. 
</li>
          <li>
Rounded corners on the control border, 
</li>
          <li>
Missing a password character to display when characters are typed.</li>
        </ul>
        <p>
The next sections will look at adding applying styles to the PasswordBox so that it
is consistent with the rest of the plug-in.
</p>
        <h2>
          <a name="PasswordBoxStyles">PasswordBox Styles</a>
        </h2>
        <p>
Adjusting The style of the password box can be performed by altering the UserControl
resources of the StandardSettings.xaml. An example of how apply the rounded corners
is provided by Tamir Khason on the <a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/e4e0c12f-b8df-4bb0-b0df-aef359b241da/">msdn
forums</a>. Tweaking example slightly to only have a border radius of 2 gives the
following xaml to be added to the xaml file.
</p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cbfb90a9-cf18-494d-9e84-7290d6a1776f" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">&lt;UserControl.Resources&gt;
    &lt;Style TargetType="PasswordBox"&gt;
        &lt;Setter Property="PasswordChar" Value="●"/&gt;
        &lt;Setter Property="KeyboardNavigation.TabNavigation" Value="None"/&gt;
        &lt;Setter Property="BorderThickness" Value="1"/&gt;
        &lt;Setter Property="HorizontalContentAlignment" Value="Left"/&gt;
        &lt;Setter Property="Padding" Value="1"/&gt;
        &lt;Setter Property="FocusVisualStyle" Value="{x:Null}"/&gt;
        &lt;Setter Property="AllowDrop" Value="true"/&gt;
        &lt;Setter Property="Template"&gt;
            &lt;Setter.Value&gt;
                &lt;ControlTemplate TargetType="PasswordBox"&gt;
                    &lt;Border CornerRadius="2" x:Name="Bd" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="Black" BorderThickness="1" OpacityMask="{x:Null}"&gt;
                        &lt;ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost" Template="{DynamicResource ScrollViewerControlTemplate1}"/&gt;
                    &lt;/Border&gt;
                    &lt;ControlTemplate.Triggers&gt;
                        &lt;Trigger Property="IsEnabled" Value="false"&gt;
                            &lt;Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/&gt;
                            &lt;Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/&gt;
                        &lt;/Trigger&gt;
                    &lt;/ControlTemplate.Triggers&gt;
                &lt;/ControlTemplate&gt;
            &lt;/Setter.Value&gt;
        &lt;/Setter&gt;
    &lt;/Style&gt;
&lt;/UserControl.Resources&gt;</pre>
        </div>
        <p>
Which gives the following output
</p>
        <p>
          <img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/PasswordBoxWithRoundedCorners.jpg" />
        </p>
        <p>
This style is much closer, but it gives the impression that the password box is not
editable by the user. In the next section I will make use Redgate’s .Net Reflector
to determine the styles used by the Expression Encoder UI to provide a more consistent
look and feel.
</p>
        <h2>
          <a name="InvestigatingDefaultStyles">Investigating Default Styles</a>
        </h2>
        <p>
The expression encoder is written using Microsoft.Net and WPF. As result the styles
and user interface as stored within the application assemblies and binary files. Using <a href="http://www.red-gate.com/products/reflector/">Redgates
.Net Reflector</a> together with the <a href="http://www.codeplex.com/reflectoraddins/Wiki/View.aspx?title=BamlViewer&amp;referringTitle=Home">BAML
viewer addin</a> available on codeplex we can look inside these file and discover
the styles used in the application.
</p>
        <p>
The main WPF application is located in &lt;Program Files&gt;\Microsoft Expression\Encoder
2\EncoderUI.exe and the english resource files that include the xaml for the application
is located in &lt;Program Files&gt;\Microsoft Expression\Encoder 2\en\EncoderUI.resources.dll.
Opening these files in reflector we are able to look at the implementation of the
application.
</p>
        <p>
 <img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/RegateNetReflectorResourcesPasswordDialog.jpg" /></p>
        <p>
Looking at the xaml the style for a password box within the resources assembly the
dynamic resource BackgroundBrush should be applied for the BorderBrush and the Background
properties of the PasswordBox.
</p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:7843839c-b5fa-4104-97b7-315c7be03697" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">&lt;Style x:Uid="Style_84" TargetType="{x:Type PasswordBox}"&gt;
    &lt;Setter x:Uid="Setter_1349" Property="BorderBrush" Value="{DynamicResource BackgroundBrush}" /&gt;
    &lt;Setter x:Uid="Setter_1350" Property="Foreground" Value="{DynamicResource Text1Brush}" /&gt;
    &lt;Setter x:Uid="Setter_1351" Property="Background" Value="{DynamicResource BackgroundBrush}" /&gt;
    &lt;Setter x:Uid="Setter_1146" Property="FontFamily" Value="{DynamicResource {x:Static MessageFontFamily}}" /&gt;
    &lt;Setter x:Uid="Setter_1147" Property="FontSize" Value="{DynamicResource {x:Static MessageFontSize}}" /&gt;
    &lt;Setter x:Uid="Setter_1148" Property="FontWeight" Value="{DynamicResource {x:Static MessageFontWeight}}" /&gt;
&lt;/Style&gt;</pre>
        </div>
        <p>
        </p>
        <h2>
          <a name="FinalVersion">Final Version</a>
        </h2>
        <p>
Applying the style changes in the last section provides the following UserControl.Resources
section. 
</p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:97a5c392-7402-4958-bd8d-1faefaa4bd29" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">&lt;UserControl.Resources&gt;
    &lt;Style TargetType="PasswordBox"&gt;
        &lt;Setter Property="PasswordChar" Value="●"/&gt;
        &lt;Setter Property="KeyboardNavigation.TabNavigation" Value="None"/&gt;
        &lt;Setter Property="BorderThickness" Value="1"/&gt;
        &lt;Setter Property="HorizontalContentAlignment" Value="Left"/&gt;
        &lt;Setter Property="Padding" Value="1"/&gt;
        &lt;Setter Property="FocusVisualStyle" Value="{x:Null}"/&gt;
        &lt;Setter Property="AllowDrop" Value="true"/&gt;
        &lt;Setter Property="Template"&gt;
            &lt;Setter.Value&gt;
                &lt;ControlTemplate TargetType="PasswordBox"&gt;
                    &lt;Border CornerRadius="2" x:Name="Bd" Background="{DynamicResource BackgroundBrush}" BorderBrush="{DynamicResource BackgroundBrush}" BorderThickness="1" OpacityMask="{x:Null}"&gt;
                        &lt;ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost" Template="{DynamicResource ScrollViewerControlTemplate1}"/&gt;
                    &lt;/Border&gt;
                    &lt;ControlTemplate.Triggers&gt;
                        &lt;Trigger Property="IsEnabled" Value="false"&gt;
                            &lt;Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/&gt;
                            &lt;Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/&gt;
                        &lt;/Trigger&gt;
                    &lt;/ControlTemplate.Triggers&gt;
                &lt;/ControlTemplate&gt;
            &lt;/Setter.Value&gt;
        &lt;/Setter&gt;
    &lt;/Style&gt;
&lt;/UserControl.Resources&gt;</pre>
        </div>
        <p>
With an output of 
</p>
        <p>
          <img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/PasswordBoxWithUpdatedBackground.jpg" />
        </p>
        <h2>
          <a name="Review">Review</a>
        </h2>
        <p>
So there we have it, the plug-in look and feel was updated by altering the XAML to
make use of Password box. The changes required the use of WPF attached properties
to ensure the data binding continues to work with he original code. To make the user
interface look consistent with rest of the plug-in UserControl resources where used
to apply the correct styles and resources.
</p>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=d3febb59-26c6-408c-8986-77b9a496bca6" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/zyIZ9Y7FDOU" height="1" width="1" /></body>
      <title>Extending the Expression Encoder 2 FTP Publishing Plug-in – Adding a WPF PasswordBox And UserControl Style</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,d3febb59-26c6-408c-8986-77b9a496bca6.aspx</guid>
      <link>http://www.garchibald.com/blog/2009/02/06/ExtendingTheExpressionEncoder2FTPPublishingPluginAddingAWPFPasswordBoxAndUserControlStyle.aspx</link>
      <pubDate>Fri, 06 Feb 2009 02:53:31 GMT</pubDate>
      <description>&lt;p&gt;
In this post I will cover the changes required to use a PasswordBox control to display
the FTP password. 
&lt;/p&gt;
&lt;p&gt;
The following links a quick reference to the topics covered:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#FTPPluginOverview"&gt;FTP Plug-in Overview&lt;/a&gt; – Quick description of the plug-in
control created by Tim Heuer. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#FTPPluginChanges"&gt;FTP Plug-in Changes&lt;/a&gt; – Steps to change the plug-in
to use a PasswordBox control instead of TextBox. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#TestingTheChanges"&gt;Testing The Changes&lt;/a&gt; – Describes testing the changes
with Expression Encoder and the issues encountered. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#PasswordBoxStyles"&gt;PasswordBox Styles&lt;/a&gt; – Describes to changes made to
alter the style for the PasswordBox control so that it has consistent look and feel. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#InvestigatingDefaultStyles"&gt;Investigating Default Styles&lt;/a&gt; - Investigating
the Expression Encoder WPF Styles using Redgate’s .Net Reflector. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#FinalVersion"&gt;Final Version&lt;/a&gt; – Describes the final version incorporating
the style changes in the previous sections. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#Review"&gt;Review&lt;/a&gt; – Describes the step taken to modify the plug-in to make
use the of a PasswordBox control.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Technologies Used
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Microsoft Visual Studio 2008 (with .Net 3.5 SP1 &lt;a href="http://www.microsoft.com/net/"&gt;installed&lt;/a&gt;) 
&lt;/li&gt;
&lt;li&gt;
Microsoft Expression Encoder 2 (with Expression Encoder 2 SP1 &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A29BE9F9-29E1-4E70-BF67-02D87D3E556E&amp;amp;displaylang=en"&gt;installed&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="FTPPluginOverview"&gt;FTP Plug-in Overview&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
The &lt;a href="http://www.codeplex.com/encoderftppublish"&gt;FTP Publishing Plug-in for
Encoder&lt;/a&gt; created by &lt;a href="http://timheuer.com/blog/"&gt;Tim Heuer&lt;/a&gt; allows the
encoded output of to be “published” to a FTP server for hosting. One minor issue from
a security point of view is the password is shown in clear text. As a result the password
is always visible and it could represent a security risk.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/ClearTextPassword.jpg"&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
In the next section I will look at replacing the standard WPF text TextBox control
with a PasswordBox so that the password is masked from the user.
&lt;/p&gt;
&lt;h2&gt;&lt;a name="FTPPluginChanges"&gt;FTP Plug-in Changes&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
Looking at the original XAML it is a standard TextBox that makes use of data binding
to load and save changes. 
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2ec36460-addf-430b-b968-e1738ba932c5" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,3,0" Content="Password" /&amp;gt;
&amp;lt;TextBox Name="Password" Grid.Row="2" Grid.Column="1" ToolTip="FTP account password" Margin="0,2.5,0,2.5" Text="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
The obvious change to replace this with a PasswordBox and bind to the Password property
instead of the Text property. 
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8a02ca6c-3e70-46b5-b18b-7f0436fab20e" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;        &amp;lt;Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,3,0" Content="Password" /&amp;gt;
        &amp;lt;PasswordBox  Name="Password" Grid.Row="2" Grid.Column="1" ToolTip="FTP account password" Margin="0,2.5,0,2.5" Password="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
This however generates an error. Looking at the problem further, Samuel Jack provides
the explanation in his post &lt;a href="http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html"&gt;WPF
PasswordBox and Data binding&lt;/a&gt;. In the post he discusses how the Password property
is a plain CLR property rather than a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty.aspx"&gt;Dependency
Property&lt;/a&gt;, so it doesn't support being the target of a data binding. Using Samuel’s
solution the code is easily modified to make use of attached properties by adding
a attribute namespace reference at the top of the UserControl
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8024c6c1-d5ce-4041-9068-6300866da537" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;xmlns:FtpPublish="clr-namespace:TimHeuer.Expression.FtpPublish"&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Combined with additions to the the PasswordBox xaml to make use of the attached properties
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f9cc00bc-34e8-4cc9-8317-a374cd81e711" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,3,0" Content="Password" /&amp;gt;
&amp;lt;PasswordBox  Name="Password" Grid.Row="2" Grid.Column="1" ToolTip="FTP account password" Margin="0,2.5,0,2.5" FtpPublish:PasswordBoxAssistant.BindPassword="true" FtpPublish:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
And adding the following C# class to define the implementation of the PasswordBoxAssistant
class.
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b930a322-c7bb-4a2f-94b6-5952825c049e" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;using System.Windows;
using System.Windows.Controls;

namespace TimHeuer.Expression.FtpPublish
{
    /// &amp;lt;summary&amp;gt;
    /// Class that allows a &amp;lt;see cref="PasswordBox"/&amp;gt; to be included in DataBinding using attached properties
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;
    /// Original source http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html
    /// &amp;lt;/remarks&amp;gt;
    public static class PasswordBoxAssistant
    {
        public static readonly DependencyProperty BoundPassword =
            DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));

        public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
            "BindPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));

        private static readonly DependencyProperty UpdatingPassword =
            DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant));

        private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var box = d as PasswordBox;

            // only handle this event when the property is attached to a PasswordBox
            // and when the BindPassword attached property has been set to true
            if (box == null || !GetBindPassword(d))
            {
                return;
            }

            // avoid recursive updating by ignoring the box's changed event
            box.PasswordChanged -= HandlePasswordChanged;

            var newPassword = (string)e.NewValue;

            if (!GetUpdatingPassword(box))
            {
                box.Password = newPassword;
            }

            box.PasswordChanged += HandlePasswordChanged;
        }

        private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
        {
            // when the BindPassword attached property is set on a PasswordBox,
            // start listening to its PasswordChanged event

            var box = dp as PasswordBox;

            if (box == null)
            {
                return;
            }

            var wasBound = (bool)(e.OldValue);
            var needToBind = (bool)(e.NewValue);

            if (wasBound)
            {
                box.PasswordChanged -= HandlePasswordChanged;
            }

            if (needToBind)
            {
                box.PasswordChanged += HandlePasswordChanged;
            }
        }

        private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
        {
            var box = sender as PasswordBox;

            if (box == null)
                return;

            // set a flag to indicate that we're updating the password
            SetUpdatingPassword(box, true);
            // push the new password into the BoundPassword property
            SetBoundPassword(box, box.Password);
            SetUpdatingPassword(box, false);
        }

        public static void SetBindPassword(DependencyObject dp, bool value)
        {
            dp.SetValue(BindPassword, value);
        }

        public static bool GetBindPassword(DependencyObject dp)
        {
            return (bool)dp.GetValue(BindPassword);
        }

        public static string GetBoundPassword(DependencyObject dp)
        {
            return (string)dp.GetValue(BoundPassword);
        }

        public static void SetBoundPassword(DependencyObject dp, string value)
        {
            dp.SetValue(BoundPassword, value);
        }

        private static bool GetUpdatingPassword(DependencyObject dp)
        {
            return (bool)dp.GetValue(UpdatingPassword);
        }

        private static void SetUpdatingPassword(DependencyObject dp, bool value)
        {
            dp.SetValue(UpdatingPassword, value);
        }
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;a name="TestingTheChanges"&gt;Testing The Changes&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
Copying the updated dll to the &amp;lt;Program Files&amp;gt;\Microsoft Expression\Encoder
2\Plugins folder, the plug-in now correctly loads but the password box does not have
the correct visual styles applied to it because the PasswordBox has not been included
in the template styles for the WPF plug-in.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/ChangedPasswordBoxNoStyle.jpg"&gt; 
&lt;/p&gt;
&lt;p&gt;
Overall the control is missing the following functionality:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The correct background colour. 
&lt;/li&gt;
&lt;li&gt;
Rounded corners on the control border, 
&lt;/li&gt;
&lt;li&gt;
Missing a password character to display when characters are typed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The next sections will look at adding applying styles to the PasswordBox so that it
is consistent with the rest of the plug-in.
&lt;/p&gt;
&lt;h2&gt;&lt;a name="PasswordBoxStyles"&gt;PasswordBox Styles&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
Adjusting The style of the password box can be performed by altering the UserControl
resources of the StandardSettings.xaml. An example of how apply the rounded corners
is provided by Tamir Khason on the &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/e4e0c12f-b8df-4bb0-b0df-aef359b241da/"&gt;msdn
forums&lt;/a&gt;. Tweaking example slightly to only have a border radius of 2 gives the
following xaml to be added to the xaml file.
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cbfb90a9-cf18-494d-9e84-7290d6a1776f" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;UserControl.Resources&amp;gt;
    &amp;lt;Style TargetType="PasswordBox"&amp;gt;
        &amp;lt;Setter Property="PasswordChar" Value="●"/&amp;gt;
        &amp;lt;Setter Property="KeyboardNavigation.TabNavigation" Value="None"/&amp;gt;
        &amp;lt;Setter Property="BorderThickness" Value="1"/&amp;gt;
        &amp;lt;Setter Property="HorizontalContentAlignment" Value="Left"/&amp;gt;
        &amp;lt;Setter Property="Padding" Value="1"/&amp;gt;
        &amp;lt;Setter Property="FocusVisualStyle" Value="{x:Null}"/&amp;gt;
        &amp;lt;Setter Property="AllowDrop" Value="true"/&amp;gt;
        &amp;lt;Setter Property="Template"&amp;gt;
            &amp;lt;Setter.Value&amp;gt;
                &amp;lt;ControlTemplate TargetType="PasswordBox"&amp;gt;
                    &amp;lt;Border CornerRadius="2" x:Name="Bd" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="Black" BorderThickness="1" OpacityMask="{x:Null}"&amp;gt;
                        &amp;lt;ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost" Template="{DynamicResource ScrollViewerControlTemplate1}"/&amp;gt;
                    &amp;lt;/Border&amp;gt;
                    &amp;lt;ControlTemplate.Triggers&amp;gt;
                        &amp;lt;Trigger Property="IsEnabled" Value="false"&amp;gt;
                            &amp;lt;Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/&amp;gt;
                            &amp;lt;Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/&amp;gt;
                        &amp;lt;/Trigger&amp;gt;
                    &amp;lt;/ControlTemplate.Triggers&amp;gt;
                &amp;lt;/ControlTemplate&amp;gt;
            &amp;lt;/Setter.Value&amp;gt;
        &amp;lt;/Setter&amp;gt;
    &amp;lt;/Style&amp;gt;
&amp;lt;/UserControl.Resources&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Which gives the following output
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/PasswordBoxWithRoundedCorners.jpg"&gt;
&lt;/p&gt;
&lt;p&gt;
This style is much closer, but it gives the impression that the password box is not
editable by the user. In the next section I will make use Redgate’s .Net Reflector
to determine the styles used by the Expression Encoder UI to provide a more consistent
look and feel.
&lt;/p&gt;
&lt;h2&gt;&lt;a name="InvestigatingDefaultStyles"&gt;Investigating Default Styles&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
The expression encoder is written using Microsoft.Net and WPF. As result the styles
and user interface as stored within the application assemblies and binary files. Using &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Redgates
.Net Reflector&lt;/a&gt; together with the &lt;a href="http://www.codeplex.com/reflectoraddins/Wiki/View.aspx?title=BamlViewer&amp;amp;referringTitle=Home"&gt;BAML
viewer addin&lt;/a&gt; available on codeplex we can look inside these file and discover
the styles used in the application.
&lt;/p&gt;
&lt;p&gt;
The main WPF application is located in &amp;lt;Program Files&amp;gt;\Microsoft Expression\Encoder
2\EncoderUI.exe and the english resource files that include the xaml for the application
is located in &amp;lt;Program Files&amp;gt;\Microsoft Expression\Encoder 2\en\EncoderUI.resources.dll.
Opening these files in reflector we are able to look at the implementation of the
application.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&lt;img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/RegateNetReflectorResourcesPasswordDialog.jpg"&gt;
&lt;/p&gt;
&lt;p&gt;
Looking at the xaml the style for a password box within the resources assembly the
dynamic resource BackgroundBrush should be applied for the BorderBrush and the Background
properties of the PasswordBox.
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:7843839c-b5fa-4104-97b7-315c7be03697" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;Style x:Uid="Style_84" TargetType="{x:Type PasswordBox}"&amp;gt;
    &amp;lt;Setter x:Uid="Setter_1349" Property="BorderBrush" Value="{DynamicResource BackgroundBrush}" /&amp;gt;
    &amp;lt;Setter x:Uid="Setter_1350" Property="Foreground" Value="{DynamicResource Text1Brush}" /&amp;gt;
    &amp;lt;Setter x:Uid="Setter_1351" Property="Background" Value="{DynamicResource BackgroundBrush}" /&amp;gt;
    &amp;lt;Setter x:Uid="Setter_1146" Property="FontFamily" Value="{DynamicResource {x:Static MessageFontFamily}}" /&amp;gt;
    &amp;lt;Setter x:Uid="Setter_1147" Property="FontSize" Value="{DynamicResource {x:Static MessageFontSize}}" /&amp;gt;
    &amp;lt;Setter x:Uid="Setter_1148" Property="FontWeight" Value="{DynamicResource {x:Static MessageFontWeight}}" /&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h2&gt;&lt;a name="FinalVersion"&gt;Final Version&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
Applying the style changes in the last section provides the following UserControl.Resources
section. 
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:97a5c392-7402-4958-bd8d-1faefaa4bd29" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;UserControl.Resources&amp;gt;
    &amp;lt;Style TargetType="PasswordBox"&amp;gt;
        &amp;lt;Setter Property="PasswordChar" Value="●"/&amp;gt;
        &amp;lt;Setter Property="KeyboardNavigation.TabNavigation" Value="None"/&amp;gt;
        &amp;lt;Setter Property="BorderThickness" Value="1"/&amp;gt;
        &amp;lt;Setter Property="HorizontalContentAlignment" Value="Left"/&amp;gt;
        &amp;lt;Setter Property="Padding" Value="1"/&amp;gt;
        &amp;lt;Setter Property="FocusVisualStyle" Value="{x:Null}"/&amp;gt;
        &amp;lt;Setter Property="AllowDrop" Value="true"/&amp;gt;
        &amp;lt;Setter Property="Template"&amp;gt;
            &amp;lt;Setter.Value&amp;gt;
                &amp;lt;ControlTemplate TargetType="PasswordBox"&amp;gt;
                    &amp;lt;Border CornerRadius="2" x:Name="Bd" Background="{DynamicResource BackgroundBrush}" BorderBrush="{DynamicResource BackgroundBrush}" BorderThickness="1" OpacityMask="{x:Null}"&amp;gt;
                        &amp;lt;ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost" Template="{DynamicResource ScrollViewerControlTemplate1}"/&amp;gt;
                    &amp;lt;/Border&amp;gt;
                    &amp;lt;ControlTemplate.Triggers&amp;gt;
                        &amp;lt;Trigger Property="IsEnabled" Value="false"&amp;gt;
                            &amp;lt;Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/&amp;gt;
                            &amp;lt;Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/&amp;gt;
                        &amp;lt;/Trigger&amp;gt;
                    &amp;lt;/ControlTemplate.Triggers&amp;gt;
                &amp;lt;/ControlTemplate&amp;gt;
            &amp;lt;/Setter.Value&amp;gt;
        &amp;lt;/Setter&amp;gt;
    &amp;lt;/Style&amp;gt;
&amp;lt;/UserControl.Resources&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
With an output of 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.garchibald.com/images/Expression-Encoder-FTP-Plugin/PasswordBoxWithUpdatedBackground.jpg"&gt;
&lt;/p&gt;
&lt;h2&gt;&lt;a name="Review"&gt;Review&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
So there we have it, the plug-in look and feel was updated by altering the XAML to
make use of Password box. The changes required the use of WPF attached properties
to ensure the data binding continues to work with he original code. To make the user
interface look consistent with rest of the plug-in UserControl resources where used
to apply the correct styles and resources.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=d3febb59-26c6-408c-8986-77b9a496bca6" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,d3febb59-26c6-408c-8986-77b9a496bca6.aspx</comments>
      <category>wpf</category>
      <category>xaml</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=e6078a46-e3bb-4f47-8d7d-3a4504c8820b</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,e6078a46-e3bb-4f47-8d7d-3a4504c8820b.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,e6078a46-e3bb-4f47-8d7d-3a4504c8820b.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=e6078a46-e3bb-4f47-8d7d-3a4504c8820b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <img alt="Spin And Win Thumbmail" src="http://www.garchibald.com/images/Mix09-10k/Thumbnail.jpg" />
          <img alt="10K Logo" src="http://www.garchibald.com/images/Mix09-10k/10K-Logo.jpg" />
        </p>
        <p>
        </p>
        <ul>
          <li>
            <a href="#Introduction">Introduction</a> - Brief summary of the game. 
</li>
          <li>
            <a href="#Description">Game Description</a> - Describes the different parts of the
game. 
</li>
          <li>
            <a href="#Win">Win</a> - An Example of how a win is calculated. 
</li>
          <li>
            <a href="#OtherControls">Other Controls</a> - Information, volume and social bookmarks. 
</li>
          <li>
            <a href="#Attributions">Multimedia Attributions</a> - Links to multimedia files used
in the game. 
</li>
        </ul>
        <p>
        </p>
        <h2>
          <a name="Introduction">Introduction</a>
        </h2>
        <p>
Welcome to Spin &amp; Win a Microsoft Silverlight Game created for the <a title="MIX 10K Gallery" href="http://2009.visitmix.com/MIXtify/TenKGallery.aspx">MIX09
10k Challenge</a>.
</p>
        <p>
Spin &amp; Win is a multimedia slot machine game that starts with an initial credit
balance of 500. The game keeps a record of your current balance so you can start it
again and continue from where you left off.
</p>
        <p>
Just select the amount you want to bet and press the SPIN button to begin, Good Luck!
</p>
        <h2>
          <a name="Description">Game Description</a>
        </h2>
        <p>
          <img style="width : 300px; border:1px solid black" alt="Loading" src="http://www.garchibald.com/images/Mix09-10k/Loading.jpg" />
        </p>
        <p>
Initially as the game loads, it will display a loading text with a percentage complete.
Once the game is loaded the loading text will disappear and the game will start.
</p>
        <p>
          <img class="screenshot" alt="Spin &amp; Win Screenshot" src="http://www.garchibald.com/images/Mix09-10k/FullScreenShot.jpg" />
        </p>
        <p>
Once the game has been started by clicking on SPIN you can use the Enter key, or change
your bet &amp; spin again.
</p>
        <p>
          <img class="screenshot" alt="Example Current Status" src="http://www.garchibald.com/images/Mix09-10k/CurrentStatus.jpg" />
        </p>
        <p>
There are 3 horizontal lines can be played with the default being line 1 only. You
can change either the number of lines to place a bet on or the credits per line by
clicking on the buttons at the bottom of the game. The selected amount is indicated
by a lighter grey button.
</p>
        <p>
          <img class="screenshot" alt="Example Number Of Lines" src="http://www.garchibald.com/images/Mix09-10k/NumberOfLines.jpg" />
          <img class="screenshot" alt="Example Number Of Lines" src="http://www.garchibald.com/images/Mix09-10k/CreditsPerLine.jpg" />
        </p>
        <p>
If a play line is not selected it will be greyed out to indicate that it will not
be included in a win.
</p>
        <p>
          <img style="border: 1px solid black; height: 200px;" alt="Example of online slot lines 1 selected" src="http://www.garchibald.com/images/Mix09-10k/SelectedSlotLines.jpg" />
          <img style="border: 1px solid black; height: 200px;" alt="Example of all slot lines in the game selected" src="http://www.garchibald.com/images/Mix09-10k/AllLinesSelected.jpg" />
        </p>
        <h3>Example: Line 1 Selected, All Lines Selected
</h3>
        <p>
If you want to "cash-in" your virtual credits you can click on the PAYOUT button.
This will reset the credits total to zero and ask you if you wish to play again.
</p>
        <p>
          <img class="screenshot" alt="Example Number Of Lines" src="http://www.garchibald.com/images/Mix09-10k/PlayAgain.jpg" />
        </p>
        <h2>
          <a name="Win">Win</a>
        </h2>
        <p>
In the example below 3 lines have been selected to play, with 10 credits per line.
</p>
        <p>
          <img class="screenshot" alt="Example Payout" src="http://www.garchibald.com/images/Mix09-10k/WinExample.jpg" />
        </p>
        <p>
On the top line there 3 apples. The total win amount is 3 Apples (10 Credits) x 10
Credits Per Line = 100 Credits. 
</p>
        <h2>
          <a name="OtherControls">Other Controls</a>
        </h2>
        <p>
The information icon in the bottom left will open this page.
</p>
        <p>
          <img alt="Information Icon" src="http://www.garchibald.com/images/Mix09-10k/InfoIcon.jpg" />
        </p>
        <p>
The volume on/off will toggle the audio sound for the reel spin, winning fanfare and
payout.
</p>
        <p>
          <img alt="Toggle Volumne On/Off" src="http://www.garchibald.com/images/Mix09-10k/VolumeOnOff.jpg" />
        </p>
        <p>
The social bookmark icons under the logo allow you to easily share and link to the
game using Delicious, Digg, StumbleUpon, Technorati, Twitter and Email. NOTE: All
the trademarks and logos are the property of their respective owners.
</p>
        <p>
          <img alt="Toggle Volumne On/Off" src="http://www.garchibald.com/images/Mix09-10k/SocialBookmarks.jpg" />
        </p>
        <h2>
          <a name="Attributions">Multimedia Attributions</a>
        </h2>
        <p>
The skin for the game uses the following media items:
</p>
        <h3>Info Icon
</h3>
        <div style="padding-left: 20px; width: 500px;">
          <h4>By <a target="_blank" href="http://mazenl77.deviantart.com/">Mazenl77</a> - Creative
Commons Attribution 3.0 Unported.
</h4>
          <p>
            <a target="_blank" href="http://www.iconspedia.com/pack/nx10-1-6/">1603 PNG</a>
            <br />
          </p>
        </div>
        <h3>Samples used from Freesound
</h3>
        <h4 style="padding-left: 20px;">January 19, 2009
</h4>
        <div style="padding-left: 20px; width: 500px;">
          <h4>By <a target="_blank" href="http://www.freesound.org/usersViewSingle.php?id=8043">dobroide</a> - <a target="_blank" href="http://creativecommons.org/licenses/by-nd/2.0/">Creative
Commons License</a></h4>
          <p>
            <a target="_blank" href="http://www.freesound.org/samplesViewSingle.php?id=9056">slot.machine.arcade.mp3</a>
            <br />
          </p>
        </div>
        <h3>Social Bookmark Icons
</h3>
        <div style="padding-left: 20px; width: 500px;">
          <h4>By <a target="_blank" href="http://www.snap2objects.com/2007/11/06/free-vector-social-bookmark-icons/">mao</a> - <a target="_blank" href="http://creativecommons.org/licenses/by/3.0/" rel="license">Creative
Commons Attribution 3.0 License</a>.
</h4>
        </div>
        <h3>Speaker Icon
</h3>
        <div style="padding-left: 20px; width: 500px;">
          <h4>By <a target="_blank" href="http://mazenl77.deviantart.com/">Mazenl77</a> - Creative
Commons Attribution 3.0 Unported.
</h4>
          <p>
            <a target="_blank" href="http://www.iconspedia.com/icon/speaker-1628.html">256x256px
PNG</a>
            <br />
          </p>
        </div>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=e6078a46-e3bb-4f47-8d7d-3a4504c8820b" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/JTpC4JJVE7I" height="1" width="1" /></body>
      <title>Mix09 10k Contest Entry – Spin And Win – Information And Help</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,e6078a46-e3bb-4f47-8d7d-3a4504c8820b.aspx</guid>
      <link>http://www.garchibald.com/blog/2009/01/24/Mix0910kContestEntrySpinAndWinInformationAndHelp.aspx</link>
      <pubDate>Sat, 24 Jan 2009 10:30:09 GMT</pubDate>
      <description>&lt;p&gt;
&lt;img alt="Spin And Win Thumbmail" src="http://www.garchibald.com/images/Mix09-10k/Thumbnail.jpg"&gt;&lt;img alt="10K Logo" src="http://www.garchibald.com/images/Mix09-10k/10K-Logo.jpg"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#Introduction"&gt;Introduction&lt;/a&gt; - Brief summary of the game. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#Description"&gt;Game Description&lt;/a&gt; - Describes the different parts of the
game. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#Win"&gt;Win&lt;/a&gt; - An Example of how a win is calculated. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#OtherControls"&gt;Other Controls&lt;/a&gt; - Information, volume and social bookmarks. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#Attributions"&gt;Multimedia Attributions&lt;/a&gt; - Links to multimedia files used
in the game. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h2&gt;&lt;a name="Introduction"&gt;Introduction&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
Welcome to Spin &amp;amp; Win a Microsoft Silverlight Game created for the &lt;a title="MIX 10K Gallery" href="http://2009.visitmix.com/MIXtify/TenKGallery.aspx"&gt;MIX09
10k Challenge&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Spin &amp;amp; Win is a multimedia slot machine game that starts with an initial credit
balance of 500. The game keeps a record of your current balance so you can start it
again and continue from where you left off.
&lt;/p&gt;
&lt;p&gt;
Just select the amount you want to bet and press the SPIN button to begin, Good Luck!
&lt;/p&gt;
&lt;h2&gt;&lt;a name="Description"&gt;Game Description&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
&lt;img style="width : 300px; border:1px solid black" alt="Loading" src="http://www.garchibald.com/images/Mix09-10k/Loading.jpg"&gt;
&lt;/p&gt;
&lt;p&gt;
Initially as the game loads, it will display a loading text with a percentage complete.
Once the game is loaded the loading text will disappear and the game will start.
&lt;/p&gt;
&lt;p&gt;
&lt;img class="screenshot" alt="Spin &amp;amp; Win Screenshot" src="http://www.garchibald.com/images/Mix09-10k/FullScreenShot.jpg"&gt;
&lt;/p&gt;
&lt;p&gt;
Once the game has been started by clicking on SPIN you can use the Enter key, or change
your bet &amp;amp; spin again.
&lt;/p&gt;
&lt;p&gt;
&lt;img class="screenshot" alt="Example Current Status" src="http://www.garchibald.com/images/Mix09-10k/CurrentStatus.jpg"&gt;
&lt;/p&gt;
&lt;p&gt;
There are 3 horizontal lines can be played with the default being line 1 only. You
can change either the number of lines to place a bet on or the credits per line by
clicking on the buttons at the bottom of the game. The selected amount is indicated
by a lighter grey button.
&lt;/p&gt;
&lt;p&gt;
&lt;img class="screenshot" alt="Example Number Of Lines" src="http://www.garchibald.com/images/Mix09-10k/NumberOfLines.jpg"&gt; &lt;img class="screenshot" alt="Example Number Of Lines" src="http://www.garchibald.com/images/Mix09-10k/CreditsPerLine.jpg"&gt; 
&lt;/p&gt;
&lt;p&gt;
If a play line is not selected it will be greyed out to indicate that it will not
be included in a win.
&lt;/p&gt;
&lt;p&gt;
&lt;img style="border: 1px solid black; height: 200px;" alt="Example of online slot lines 1 selected" src="http://www.garchibald.com/images/Mix09-10k/SelectedSlotLines.jpg"&gt; &lt;img style="border: 1px solid black; height: 200px;" alt="Example of all slot lines in the game selected" src="http://www.garchibald.com/images/Mix09-10k/AllLinesSelected.jpg"&gt; 
&lt;/p&gt;
&lt;h3&gt;Example: Line 1 Selected, All Lines Selected
&lt;/h3&gt;
&lt;p&gt;
If you want to "cash-in" your virtual credits you can click on the PAYOUT button.
This will reset the credits total to zero and ask you if you wish to play again.
&lt;/p&gt;
&lt;p&gt;
&lt;img class="screenshot" alt="Example Number Of Lines" src="http://www.garchibald.com/images/Mix09-10k/PlayAgain.jpg"&gt;
&lt;/p&gt;
&lt;h2&gt;&lt;a name="Win"&gt;Win&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
In the example below 3 lines have been selected to play, with 10 credits per line.
&lt;/p&gt;
&lt;p&gt;
&lt;img class="screenshot" alt="Example Payout" src="http://www.garchibald.com/images/Mix09-10k/WinExample.jpg"&gt; 
&lt;/p&gt;
&lt;p&gt;
On the top line there 3 apples. The total win amount is 3 Apples (10 Credits) x 10
Credits Per Line = 100 Credits. 
&lt;/p&gt;
&lt;h2&gt;&lt;a name="OtherControls"&gt;Other Controls&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
The information icon in the bottom left will open this page.
&lt;/p&gt;
&lt;p&gt;
&lt;img alt="Information Icon" src="http://www.garchibald.com/images/Mix09-10k/InfoIcon.jpg"&gt; 
&lt;/p&gt;
&lt;p&gt;
The volume on/off will toggle the audio sound for the reel spin, winning fanfare and
payout.
&lt;/p&gt;
&lt;p&gt;
&lt;img alt="Toggle Volumne On/Off" src="http://www.garchibald.com/images/Mix09-10k/VolumeOnOff.jpg"&gt; 
&lt;/p&gt;
&lt;p&gt;
The social bookmark icons under the logo allow you to easily share and link to the
game using Delicious, Digg, StumbleUpon, Technorati, Twitter and Email. NOTE: All
the trademarks and logos are the property of their respective owners.
&lt;/p&gt;
&lt;p&gt;
&lt;img alt="Toggle Volumne On/Off" src="http://www.garchibald.com/images/Mix09-10k/SocialBookmarks.jpg"&gt; 
&lt;/p&gt;
&lt;h2&gt;&lt;a name="Attributions"&gt;Multimedia Attributions&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
The skin for the game uses the following media items:
&lt;/p&gt;
&lt;h3&gt;Info Icon
&lt;/h3&gt;
&lt;div style="padding-left: 20px; width: 500px;"&gt;
&lt;h4&gt;By &lt;a target="_blank" href="http://mazenl77.deviantart.com/"&gt;Mazenl77&lt;/a&gt; - Creative
Commons Attribution 3.0 Unported.
&lt;/h4&gt;
&lt;p&gt;
&lt;a target="_blank" href="http://www.iconspedia.com/pack/nx10-1-6/"&gt;1603 PNG&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Samples used from Freesound
&lt;/h3&gt;
&lt;h4 style="padding-left: 20px;"&gt;January 19, 2009
&lt;/h4&gt;
&lt;div style="padding-left: 20px; width: 500px;"&gt;
&lt;h4&gt;By &lt;a target="_blank" href="http://www.freesound.org/usersViewSingle.php?id=8043"&gt;dobroide&lt;/a&gt; - &lt;a target="_blank" href="http://creativecommons.org/licenses/by-nd/2.0/"&gt;Creative
Commons License&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;
&lt;a target="_blank" href="http://www.freesound.org/samplesViewSingle.php?id=9056"&gt;slot.machine.arcade.mp3&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Social Bookmark Icons
&lt;/h3&gt;
&lt;div style="padding-left: 20px; width: 500px;"&gt;
&lt;h4&gt;By &lt;a target="_blank" href="http://www.snap2objects.com/2007/11/06/free-vector-social-bookmark-icons/"&gt;mao&lt;/a&gt; - &lt;a target="_blank" href="http://creativecommons.org/licenses/by/3.0/" rel="license"&gt;Creative
Commons Attribution 3.0 License&lt;/a&gt;.
&lt;/h4&gt;
&lt;/div&gt;
&lt;h3&gt;Speaker Icon
&lt;/h3&gt;
&lt;div style="padding-left: 20px; width: 500px;"&gt;
&lt;h4&gt;By &lt;a target="_blank" href="http://mazenl77.deviantart.com/"&gt;Mazenl77&lt;/a&gt; - Creative
Commons Attribution 3.0 Unported.
&lt;/h4&gt;
&lt;p&gt;
&lt;a target="_blank" href="http://www.iconspedia.com/icon/speaker-1628.html"&gt;256x256px
PNG&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=e6078a46-e3bb-4f47-8d7d-3a4504c8820b" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,e6078a46-e3bb-4f47-8d7d-3a4504c8820b.aspx</comments>
      <category>mix09</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=979ea140-b656-4106-897d-2fb62eacff0b</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,979ea140-b656-4106-897d-2fb62eacff0b.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,979ea140-b656-4106-897d-2fb62eacff0b.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=979ea140-b656-4106-897d-2fb62eacff0b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Inspired by Mix09 being held in Las Vegas the logical choice of entry was a slot machine
game. So my Silverlight entry Spin &amp; Win was created.
</p>
        <p>
          <a href="http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0094%20">
            <img src="http://www.garchibald.com/images/Mix09-10k/FullScreenShot.jpg" alt="Spin And Win Screenshot" />
          </a>
        </p>
        <p>
You can play the game online at the <a href="http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0094%20">Mix09
Site</a> and information about the game is linked within the game and is also available
from my <a href="http://www.garchibald.com/mix09_10k">Mix09 10k Information/Help page</a>.
</p>
        <p>
Keeping the entry inside the 10k limit was a definite challenge. Overall it was a
great process, diving deeper into creating a Silverlight game encompassing a whole
range of factors to create the final product:
</p>
        <ul>
          <li>
Animation of controls to create visual effects. 
</li>
          <li>
Coding optimisation techniques to minimise the size of the code. 
</li>
          <li>
Dynamically loading controls and components. 
</li>
          <li>
External links from the application e.g. Social bookmarks and Information/Help on
the game. 
</li>
          <li>
Graphic design of the game. 
</li>
          <li>
Interaction with external services. 
</li>
          <li>
State management giving the ability to save and load the state of the game.</li>
        </ul>
        <p>
Visit the  Mix site now and <a href="http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0094">add
a vote</a> and I look forward to your comments.
</p>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=979ea140-b656-4106-897d-2fb62eacff0b" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/CjaMwRnXlqY" height="1" width="1" /></body>
      <title>My Mix09 10k Contest Entry Is Live – Spin And Win</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,979ea140-b656-4106-897d-2fb62eacff0b.aspx</guid>
      <link>http://www.garchibald.com/blog/2009/01/23/MyMix0910kContestEntryIsLiveSpinAndWin.aspx</link>
      <pubDate>Fri, 23 Jan 2009 10:02:30 GMT</pubDate>
      <description>&lt;p&gt;
Inspired by Mix09 being held in Las Vegas the logical choice of entry was a slot machine
game. So my Silverlight entry Spin &amp;amp; Win was created.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0094%20"&gt;&lt;img src="http://www.garchibald.com/images/Mix09-10k/FullScreenShot.jpg" alt="Spin And Win Screenshot"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
You can play the game online at the &lt;a href="http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0094%20"&gt;Mix09
Site&lt;/a&gt; and information about the game is linked within the game and is also available
from my &lt;a href="http://www.garchibald.com/mix09_10k"&gt;Mix09 10k Information/Help page&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Keeping the entry inside the 10k limit was a definite challenge. Overall it was a
great process, diving deeper into creating a Silverlight game encompassing a whole
range of factors to create the final product:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Animation of controls to create visual effects. 
&lt;/li&gt;
&lt;li&gt;
Coding optimisation techniques to minimise the size of the code. 
&lt;/li&gt;
&lt;li&gt;
Dynamically loading controls and components. 
&lt;/li&gt;
&lt;li&gt;
External links from the application e.g. Social bookmarks and Information/Help on
the game. 
&lt;/li&gt;
&lt;li&gt;
Graphic design of the game. 
&lt;/li&gt;
&lt;li&gt;
Interaction with external services. 
&lt;/li&gt;
&lt;li&gt;
State management giving the ability to save and load the state of the game.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Visit the&amp;nbsp; Mix site now and &lt;a href="http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0094"&gt;add
a vote&lt;/a&gt; and I look forward to your comments.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=979ea140-b656-4106-897d-2fb62eacff0b" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,979ea140-b656-4106-897d-2fb62eacff0b.aspx</comments>
      <category>mix09</category>
      <category>silverlight</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=93e64dfe-4561-4208-b315-60e86b62a265</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,93e64dfe-4561-4208-b315-60e86b62a265.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,93e64dfe-4561-4208-b315-60e86b62a265.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=93e64dfe-4561-4208-b315-60e86b62a265</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <h2>Overview
</h2>
        <p>
In this post I will provide an overview of the changes from the original wav media
files, to wma files required by the Silverlight version. 
<br /></p>
        <p>
The main sections are:
</p>
        <ul>
          <li>
            <a href="#Introduction">Introduction</a> – Discusses the background behind the use
of audio files in the original WPF version and an overview of the changes required. 
</li>
          <li>
            <a href="#CodeChanges">Code Changes</a> – Discusses the changes required to move from
win32 api implementation to the MediaElement. 
</li>
          <li>
            <a href="#AudioFileChanges">Audio File Changes</a> – Discusses uses Microsoft Expression
Media Encoder 2 to convert the wav files to wma files. 
</li>
          <li>
            <a href="#Summary">Summary</a> – Overview of the changes made and the advantages of
the change. 
<br /></li>
        </ul>
        <h2>
          <a name="Introduction">Introduction</a>
        </h2>
        <p>
As Scott indicated in his first post <a href="http://www.hanselman.com/blog/IntroducingBabySmashAWPFExperiment.aspx">Introducing
BabySmash</a>, he started using techniques that he already knew. As a result the laughs
and giggles played when a key is pressed where included as embedded wav files. When
moving to the Silverlight environment this approach require some modifications to
optimise the download experience and cater for the differences of running cross platform
within a browser. 
<br /></p>
        <h2>
          <a name="CodeChanges">Code Changes</a>
        </h2>
        <p>
The original audio files used by the WPF application where wav files as in made use
of class called Win32Audio, which wrapped calls to the underlying Windows unmanaged
win32 api’s. 
</p>
        <p>
        </p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e767aeeb-2773-44b9-b0db-60eb0bac08ec" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">    public class Win32Audio
    {
        #region WIN32 Const Definitions
        public const UInt32 SND_ASYNC = 0x0001;
        public const UInt32 SND_LOOP = 0x0008;
        public const UInt32 SND_MEMORY = 0x0004;
        public const UInt32 SND_NOSTOP = 0x0010;
        #endregion

        // this is the overload we want to play embedded resource...
        public static Dictionary&lt;string, string&gt; cachedWavs = new Dictionary&lt;string, string&gt;();
        public static object cachedWavsLock = new object();

        [DllImport("winmm.dll")]
        public static extern bool PlaySound(byte[] data, IntPtr hMod, UInt32 dwFlags);

        [DllImport("winmm.dll", SetLastError = true)]
        private static extern bool PlaySound(string pszSound, IntPtr hmod, UInt32 fdwSound);

        public void PlayWavResource(string wav)
        {
            string s = GetWavResource(wav);
            PlaySound(s, IntPtr.Zero, SND_ASYNC);
        }</pre>
        </div>
        <p>
        </p>
        <p>
For the Silverlight version pinvokes to the underlying operating system are not allowed
from  both a security point and cross platform point of view. The answer was
to implement a new class XamlAudio that makes use of the MediaElement class present
in both WPF and Silverlight to play the audio files. 
<br /></p>
        <div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9ca0baf8-22cd-46d1-861a-83d34d0db5cf" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">    public class XamlAudio
    {
        private MediaElement player;
        readonly Queue&lt;string&gt; soundsToPlay = new Queue&lt;string&gt;();
        private bool inPlay;

        private Dictionary&lt;string, Stream&gt; media = new Dictionary&lt;string, Stream&gt;();

        //TODO Add lock and config value for sound queue limit
        public void PlayWavResourceYield(string s)
        {
            if (player == null)
                return;

            if (inPlay &amp;&amp; soundsToPlay.Count &lt; 5)
            {
                soundsToPlay.Enqueue(s);
                return;
            }

            PlaySound(s);
        }</pre>
        </div>
        <p>
The second major difference in the code is the shift from  the use of embedded
audio files, as indicated in my earlier post <a href="http://www.garchibald.com/blog/2008/11/16/SilverlightBabySmashPerformanceTheAsynchronousStory.aspx">Silverlight
BabySmash Performance – The Asynchronous Story</a>, the Silverlight version asynchronously
downloads the audio files on demand. As result the initial download size for the deployed
application is smaller.
</p>
        <h2>
          <a name="AudioFileChanges">Audio File Changes</a>
          <br />
        </h2>
        <p>
The encoding format was also a major difference, changing from the use of wav files
to Window Media  Audio files (*.wma). To convert the files I used Microsoft Expression
Encoder. 
</p>
        <p>
The steps I used to convert the files where as follows: 
<br /></p>
        <ol>
          <li>
Download and install <a href="http://www.microsoft.com/expression/try-it/Default.aspx">Microsoft
Expression Encoder 2</a>. 
</li>
          <li>
Open Expression Encoder. 
</li>
          <li>
Import the existing wmv files. Either using File Import menu or by licking on the
Import button at the bottom of the window. 
</li>
          <li>
Select the Encode tab. 
</li>
          <li>
In the profile audio group expand the advanced properties. 
</li>
          <li>
Change the properties to a smaller size to optimise the smaller size. 
<ol><li>
Codec WMA 
</li><li>
Mode CBR 
</li><li>
Bitrate 20kps 
</li><li>
Sample Rate 44.1kHz 
</li><li>
Bits Per Sample 16 
</li><li>
Channels Mono</li></ol></li>
          <li>
Start the encoding process by click the encode button at the bottom of the window
or the Encode File menu item. 
</li>
          <li>
Once the encoding is complete select Output tab in the top right. 
</li>
          <li>
Open the output folder by clicking o the Open Job button in the Job Output Section.</li>
        </ol>
        <p>
From the the output folder I copied the converted wma files to the ClientBin folder
of the web site so that they where easily accessible  to the Silverlight application
when using a WebClient asynchronous download request. 
<br /></p>
        <table border="1" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td width="179">
File</td>
              <td width="138">
WAV Encoding (kbps)</td>
              <td width="132">
WAV Files Size (KB)</td>
              <td width="140">
WMA Encoding (kbps)</td>
              <td width="127">
WMA File Size (KB)</td>
            </tr>
            <tr>
              <td>
babygigl2</td>
              <td>
20</td>
              <td>
6</td>
              <td>
20</td>
              <td>
15</td>
            </tr>
            <tr>
              <td>
babylaugh</td>
              <td>
88</td>
              <td>
14</td>
              <td>
20</td>
              <td>
11</td>
            </tr>
            <tr>
              <td>
ccgiggle</td>
              <td>
88</td>
              <td>
9</td>
              <td>
20</td>
              <td>
10</td>
            </tr>
            <tr>
              <td>
EditedJackPlaysBabySmash</td>
              <td>
352</td>
              <td>
227</td>
              <td>
20</td>
              <td>
25</td>
            </tr>
            <tr>
              <td>
falling</td>
              <td>
128</td>
              <td>
29</td>
              <td>
20</td>
              <td>
14</td>
            </tr>
            <tr>
              <td>
giggle</td>
              <td>
88</td>
              <td>
15</td>
              <td>
20</td>
              <td>
13</td>
            </tr>
            <tr>
              <td>
laugingmice</td>
              <td>
89</td>
              <td>
17</td>
              <td>
20</td>
              <td>
14</td>
            </tr>
            <tr>
              <td>
rising</td>
              <td>
128</td>
              <td>
26</td>
              <td>
20</td>
              <td>
13</td>
            </tr>
            <tr>
              <td>
scooby2</td>
              <td>
20</td>
              <td>
5</td>
              <td>
20</td>
              <td>
13</td>
            </tr>
            <tr>
              <td>
smallbumblebee</td>
              <td>
705</td>
              <td>
862</td>
              <td>
20</td>
              <td>
31</td>
            </tr>
          </tbody>
        </table>
        <p>
One interesting point from the comparison of the conversion is that for the small
files with the same bit rate encoding the WMA files where larger. If further optimisation
in terms of files size is required, then this is an area that could be further investigated
to determine the exact encoding settings to trade-off audio quality against file size. 
<br /></p>
        <h2>
          <a name="Summary">Summary</a>
        </h2>
        <p>
        </p>
        <ul>
          <li>
Changes to the C# code to make use of the built in MediaElement to play the audio
files. 
</li>
          <li>
Cross platform audio support using wma files instead of wmv files. 
</li>
          <li>
Use of Expression Encoder to convert the source wmv files to a web optimised encoding. 
</li>
        </ul>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=93e64dfe-4561-4208-b315-60e86b62a265" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/o9kE59S3Z3o" height="1" width="1" /></body>
      <title>Silverlight BabySmash Audio Files</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,93e64dfe-4561-4208-b315-60e86b62a265.aspx</guid>
      <link>http://www.garchibald.com/blog/2008/12/19/SilverlightBabySmashAudioFiles.aspx</link>
      <pubDate>Fri, 19 Dec 2008 00:11:25 GMT</pubDate>
      <description>&lt;h2&gt;Overview
&lt;/h2&gt;
&lt;p&gt;
In this post I will provide an overview of the changes from the original wav media
files, to wma files required by the Silverlight version. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
The main sections are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#Introduction"&gt;Introduction&lt;/a&gt; – Discusses the background behind the use
of audio files in the original WPF version and an overview of the changes required. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#CodeChanges"&gt;Code Changes&lt;/a&gt; – Discusses the changes required to move from
win32 api implementation to the MediaElement. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#AudioFileChanges"&gt;Audio File Changes&lt;/a&gt; – Discusses uses Microsoft Expression
Media Encoder 2 to convert the wav files to wma files. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#Summary"&gt;Summary&lt;/a&gt; – Overview of the changes made and the advantages of
the change. 
&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="Introduction"&gt;Introduction&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
As Scott indicated in his first post &lt;a href="http://www.hanselman.com/blog/IntroducingBabySmashAWPFExperiment.aspx"&gt;Introducing
BabySmash&lt;/a&gt;, he started using techniques that he already knew. As a result the laughs
and giggles played when a key is pressed where included as embedded wav files. When
moving to the Silverlight environment this approach require some modifications to
optimise the download experience and cater for the differences of running cross platform
within a browser. 
&lt;br&gt;
&lt;/p&gt;
&lt;h2&gt;&lt;a name="CodeChanges"&gt;Code Changes&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
The original audio files used by the WPF application where wav files as in made use
of class called Win32Audio, which wrapped calls to the underlying Windows unmanaged
win32 api’s. 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e767aeeb-2773-44b9-b0db-60eb0bac08ec" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;    public class Win32Audio
    {
        #region WIN32 Const Definitions
        public const UInt32 SND_ASYNC = 0x0001;
        public const UInt32 SND_LOOP = 0x0008;
        public const UInt32 SND_MEMORY = 0x0004;
        public const UInt32 SND_NOSTOP = 0x0010;
        #endregion

        // this is the overload we want to play embedded resource...
        public static Dictionary&amp;lt;string, string&amp;gt; cachedWavs = new Dictionary&amp;lt;string, string&amp;gt;();
        public static object cachedWavsLock = new object();

        [DllImport("winmm.dll")]
        public static extern bool PlaySound(byte[] data, IntPtr hMod, UInt32 dwFlags);

        [DllImport("winmm.dll", SetLastError = true)]
        private static extern bool PlaySound(string pszSound, IntPtr hmod, UInt32 fdwSound);

        public void PlayWavResource(string wav)
        {
            string s = GetWavResource(wav);
            PlaySound(s, IntPtr.Zero, SND_ASYNC);
        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
For the Silverlight version pinvokes to the underlying operating system are not allowed
from&amp;nbsp; both a security point and cross platform point of view. The answer was
to implement a new class XamlAudio that makes use of the MediaElement class present
in both WPF and Silverlight to play the audio files. 
&lt;br&gt;
&lt;/p&gt;
&lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9ca0baf8-22cd-46d1-861a-83d34d0db5cf" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;    public class XamlAudio
    {
        private MediaElement player;
        readonly Queue&amp;lt;string&amp;gt; soundsToPlay = new Queue&amp;lt;string&amp;gt;();
        private bool inPlay;

        private Dictionary&amp;lt;string, Stream&amp;gt; media = new Dictionary&amp;lt;string, Stream&amp;gt;();

        //TODO Add lock and config value for sound queue limit
        public void PlayWavResourceYield(string s)
        {
            if (player == null)
                return;

            if (inPlay &amp;amp;&amp;amp; soundsToPlay.Count &amp;lt; 5)
            {
                soundsToPlay.Enqueue(s);
                return;
            }

            PlaySound(s);
        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
The second major difference in the code is the shift from&amp;nbsp; the use of embedded
audio files, as indicated in my earlier post &lt;a href="http://www.garchibald.com/blog/2008/11/16/SilverlightBabySmashPerformanceTheAsynchronousStory.aspx"&gt;Silverlight
BabySmash Performance – The Asynchronous Story&lt;/a&gt;, the Silverlight version asynchronously
downloads the audio files on demand. As result the initial download size for the deployed
application is smaller.
&lt;/p&gt;
&lt;h2&gt;&lt;a name="AudioFileChanges"&gt;Audio File Changes&lt;/a&gt; 
&lt;br&gt;
&lt;/h2&gt;
&lt;p&gt;
The encoding format was also a major difference, changing from the use of wav files
to Window Media&amp;nbsp; Audio files (*.wma). To convert the files I used Microsoft Expression
Encoder. 
&lt;/p&gt;
&lt;p&gt;
The steps I used to convert the files where as follows: 
&lt;br&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Download and install &lt;a href="http://www.microsoft.com/expression/try-it/Default.aspx"&gt;Microsoft
Expression Encoder 2&lt;/a&gt;. 
&lt;/li&gt;
&lt;li&gt;
Open Expression Encoder. 
&lt;/li&gt;
&lt;li&gt;
Import the existing wmv files. Either using File Import menu or by licking on the
Import button at the bottom of the window. 
&lt;/li&gt;
&lt;li&gt;
Select the Encode tab. 
&lt;/li&gt;
&lt;li&gt;
In the profile audio group expand the advanced properties. 
&lt;/li&gt;
&lt;li&gt;
Change the properties to a smaller size to optimise the smaller size. 
&lt;ol&gt;
&lt;li&gt;
Codec WMA 
&lt;/li&gt;
&lt;li&gt;
Mode CBR 
&lt;/li&gt;
&lt;li&gt;
Bitrate 20kps 
&lt;/li&gt;
&lt;li&gt;
Sample Rate 44.1kHz 
&lt;/li&gt;
&lt;li&gt;
Bits Per Sample 16 
&lt;/li&gt;
&lt;li&gt;
Channels Mono&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
Start the encoding process by click the encode button at the bottom of the window
or the Encode File menu item. 
&lt;/li&gt;
&lt;li&gt;
Once the encoding is complete select Output tab in the top right. 
&lt;/li&gt;
&lt;li&gt;
Open the output folder by clicking o the Open Job button in the Job Output Section.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
From the the output folder I copied the converted wma files to the ClientBin folder
of the web site so that they where easily accessible&amp;nbsp; to the Silverlight application
when using a WebClient asynchronous download request. 
&lt;br&gt;
&lt;/p&gt;
&lt;table border="1" cellpadding="0" cellspacing="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="179"&gt;
File&lt;/td&gt;
&lt;td width="138"&gt;
WAV Encoding (kbps)&lt;/td&gt;
&lt;td width="132"&gt;
WAV Files Size (KB)&lt;/td&gt;
&lt;td width="140"&gt;
WMA Encoding (kbps)&lt;/td&gt;
&lt;td width="127"&gt;
WMA File Size (KB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
babygigl2&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
6&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
babylaugh&lt;/td&gt;
&lt;td&gt;
88&lt;/td&gt;
&lt;td&gt;
14&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
ccgiggle&lt;/td&gt;
&lt;td&gt;
88&lt;/td&gt;
&lt;td&gt;
9&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
EditedJackPlaysBabySmash&lt;/td&gt;
&lt;td&gt;
352&lt;/td&gt;
&lt;td&gt;
227&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
falling&lt;/td&gt;
&lt;td&gt;
128&lt;/td&gt;
&lt;td&gt;
29&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
giggle&lt;/td&gt;
&lt;td&gt;
88&lt;/td&gt;
&lt;td&gt;
15&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
laugingmice&lt;/td&gt;
&lt;td&gt;
89&lt;/td&gt;
&lt;td&gt;
17&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
rising&lt;/td&gt;
&lt;td&gt;
128&lt;/td&gt;
&lt;td&gt;
26&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
scooby2&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
5&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
smallbumblebee&lt;/td&gt;
&lt;td&gt;
705&lt;/td&gt;
&lt;td&gt;
862&lt;/td&gt;
&lt;td&gt;
20&lt;/td&gt;
&lt;td&gt;
31&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
One interesting point from the comparison of the conversion is that for the small
files with the same bit rate encoding the WMA files where larger. If further optimisation
in terms of files size is required, then this is an area that could be further investigated
to determine the exact encoding settings to trade-off audio quality against file size. 
&lt;br&gt;
&lt;/p&gt;
&lt;h2&gt;&lt;a name="Summary"&gt;Summary&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Changes to the C# code to make use of the built in MediaElement to play the audio
files. 
&lt;/li&gt;
&lt;li&gt;
Cross platform audio support using wma files instead of wmv files. 
&lt;/li&gt;
&lt;li&gt;
Use of Expression Encoder to convert the source wmv files to a web optimised encoding. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=93e64dfe-4561-4208-b315-60e86b62a265" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,93e64dfe-4561-4208-b315-60e86b62a265.aspx</comments>
      <category>babysmash</category>
      <category>silverlight</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=cacc676a-6f06-41e3-a412-aa31dbe0e74e</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,cacc676a-6f06-41e3-a412-aa31dbe0e74e.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,cacc676a-6f06-41e3-a412-aa31dbe0e74e.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cacc676a-6f06-41e3-a412-aa31dbe0e74e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <h2>Overview
</h2>
        <p>
In this blog entry I will cover some the factors effecting perceived performance and
the asynchronous code used to optimise the user experience. 
</p>
        <h2>Introduction
</h2>
        <p>
When looking at the performance of the BabySmash Silverlight application it was important
to look at a number of factors to help improve the perceived performance of the application.
These included:
</p>
        <ul>
          <li>
Initial download size. 
</li>
          <li>
Use of a secondary assembly. 
</li>
          <li>
Use of media files. 
</li>
        </ul>
        <p>
So let's start of by profiling the current application see what has been done.
</p>
        <p>
          <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="HttpProfile" border="0" alt="Http Download Profile" src="http://www.garchibald.com/images/Silverlight-BabySmash-Performance-The-Asynchronous-Story/HttpProfile.jpg" width="584" height="509" usemap="#httpProfileMap" />
        </p>
        <map id="httpProfileMap" name="httpProfileMap">
          <area href="#InitialDownload" shape="rect" alt="Initial Download" coords="11,306,145,336" />
          <area href="#InitialDownload" shape="rect" alt="Initial Download" coords="9,384,211,410" />
          <area href="#SecondaryDownload" shape="rect" alt="Secondary Download" coords="203,309,359,340" />
          <area href="#SecondaryDownload" shape="rect" alt="Secondary Download" coords="9,409,249,434" />
          <area href="#LoadOnDemand" shape="rect" alt="Load On Demand" coords="434,310,571,337" />
          <area href="#LoadOnDemand" shape="rect" alt="Load On Demand" coords="10,433,248,500" />
        </map>
        <p>
Looking at the HTTP profile of the application there are three distinct phases:
</p>
        <ol>
          <li>
Synchronous download of the <a href="#InitialDownload">initial html code and the Silverlight
application</a>. 
</li>
          <li>
Asynchronous download of <a href="#SecondaryDownload">secondary components</a>. 
</li>
          <li>
Asynchronous download of media files <a href="#LoadOnDemand">on demand</a> as the
user presses keys.</li>
        </ol>
        <p>
          <strong>
            <a name="InitialDownload">Initial Download</a>
          </strong>
        </p>
        <p>
The default.htm file together with the initial BabySmashWeb.xap combined are around
60kb. This xap file contains all the code necessary to interact with the user, request
the additional resources and log information to the central ADO.Net Data Service.
</p>
        <p>
Using this approach the loading phase of the the Silverlight application is very short
and the user immediately shown the “Smash Canvas” as quickly a possible. 
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:22d65f87-7d80-4eb5-bc08-843aa888e09b" class="wlWriterEditableSmartContent">
          <pre name="code" class="xml">    &lt;div id="silverlightControlHost"&gt;
        &lt;object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"&gt;
            &lt;param name="source" value="ClientBin/BabySmashWeb.xap"/&gt;
            &lt;param name="onerror" value="onSilverlightError" /&gt;
            &lt;param name="background" value="white" /&gt;
            &lt;param name="minRuntimeVersion" value="2.0.31005.0" /&gt;
            &lt;param name="autoUpgrade" value="true" /&gt;
            &lt;param name="initParams" value="logKeys=true" /&gt;
            &lt;a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"&gt;
	            &lt;img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/&gt;
            &lt;/a&gt;
        &lt;/object&gt;
        &lt;iframe style='visibility:hidden;height:0;width:0;border:0px'&gt;&lt;/iframe&gt;
    &lt;/div&gt;</pre>
        </div>
        <p>
        </p>
        <p>
          <strong>
            <a name="SecondaryDownload">Secondary Download</a>
          </strong>
        </p>
        <p>
Once the application is loaded, the constructor of the main code behind Page class
is called
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:da725dfa-9c2c-4a24-b70a-275649cd0c34" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">        public Page()
        {
            InitializeComponent();

            var controller = new Controller();
            controller.Launch();
            mainPage = controller.Windows[0];

            KeyUp += new KeyEventHandler(Page_KeyUp);

            LayoutRoot.Children.Add(mainPage);
        }</pre>
        </div>
        <p>
Which calls starts a Controller class, which in turn starts the asynchronous requests
for the letters and the initial media file.
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:76737be7-54a5-4b40-ad54-5f6f0d8e4f3f" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">       public void Launch()
       {
           CheckForUpdatesAsync();

           SetupInitialWindowState();

           //here to pre-cache letter
           CoolLetter.InitLetterStateAsync();

           //Startup sound
           audio.PlayWavResourceYield(".Resources.Sounds." + "EditedJackPlaysBabySmash.wav");
       }</pre>
        </div>
        <p>
        </p>
        <p>
        </p>
        <p>
The rest of this section will discuss how the letters stored in the secondary BabySmashEnglishLetters.xap
are downloaded and stored for use when the user presses a key. The initial technique
for loading the audio files is discussed in the implementation of PlayWavResourceYeild
in the <a href="#LoadOnDemand">Load On Demand</a> section below.
</p>
        <p>
        </p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:932969bf-421c-471a-8558-bd25b5be91e1" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">   public partial class CoolLetter 
	{
      public CoolLetter()
      {
         this.InitializeComponent();
      }

	    static readonly Dictionary&lt;string, string&gt; _letters = InitLetters();

        public static void InitLetterStateAsync()
        {
            // No work to do as the private _letters will be initialised above
        }</pre>
        </div>
        <p>
        </p>
        <p>
The InitLetters method is called by the .Net Framework when the static class is initialised.
The method utilises a WebClient class instance to asynchronously download the required
secondary assembly 
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:bff9f2e3-9797-4af9-ab96-5f74854e1d31" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">       private static Dictionary&lt;string, string&gt; InitLetters()
       {
           var addressUri = new Uri("BabySmashEnglishLetters.xap", UriKind.Relative);
           var letterLoader = new WebClient();
           letterLoader.OpenReadCompleted += letterAssemblyLoaded;
           letterLoader.OpenReadAsync(addressUri);
           return new Dictionary&lt;string, string&gt;();
       }</pre>
        </div>
        <p>
        </p>
        <p>
Once the asynchronous call is completed, reflection is used to dynamically call the
GenerateAlphanumericCharacters method of the AlphaNumericLetterGenerator class. 
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9c10caac-a8aa-4b39-a4e7-bdcc75f94798" class="wlWriterEditableSmartContent">
          <pre name="code" class="c#">	    private static void letterAssemblyLoaded(object sender, OpenReadCompletedEventArgs e)
	    {
	        if ((e.Error != null) || e.Cancelled) return;

	        // Convert the downloaded stream into an assembly
	        var a = LoadAssemblyFromXap("BabySmashLetters.dll", e.Result);

	        var generator = a.CreateInstance("BabySmashLetters.AlphaNumericLetterGenerator");

	        if (generator == null) return;


	        var generated = generator.GetType().InvokeMember("GenerateAlpanumericCharacters", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, generator,null) as Dictionary&lt;string, string&gt;;
            if ( generated == null ) return;
	        foreach (var pair in generated)
	        {
	            _letters.Add(pair.Key, pair.Value);
	        }
	    }
</pre>
        </div>
Loading the assembly is achieved by extracting the requested assembly from the xap
stream as follows.
<p /><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9ae34c5c-eaa7-4c91-8d41-7aabae51e5ec" class="wlWriterEditableSmartContent"><pre name="code" class="c#">	    public static Assembly LoadAssemblyFromXap(string relativeUriString, Stream xapPackageStream)
        {
            var uri = new Uri(relativeUriString, UriKind.Relative);
            var xapPackageSri = new StreamResourceInfo(xapPackageStream, null);
            var assemblySri = Application.GetResourceStream(xapPackageSri, uri);

            var assemblyPart = new AssemblyPart();
            var a = assemblyPart.Load(assemblySri.Stream);
            return a;
        }</pre></div><p><strong><a name="LoadOnDemand">Load On Demand</a></strong></p><p>
By the time that the third stage of load on demand media files is reached the main
application is loaded, the secondary assembly is loading or loaded and the introduction
sound file has played. This has resulted in the download of around 160kb of files
and kept the time wait time for the user to a minimum.
</p><p>
Loading the external dependencies has also given us the following advantages:
</p><ul><li>
Allow for the possibility of localising the application to other non-english languages. 
</li><li>
Allow media files to be updated independently of the compiled code. 
</li><li>
Allow the media files to to be sourced from alternative locations e.g. File stored
locally on the client computer. 
</li><li>
Reduced bandwidth from 406kb for users that visit the page but do not start using
the application.</li></ul><p>
The process for loading the additional media files is similar to the process to load
the assembly secondary xap file but has the additional complexity that the user can
be pressing keys very quickly. As a result the application needs to respond very quickly
by queuing the key requests then asynchronously downloading and playing the associated
sound file.
</p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:92cbb09d-e85b-4e5e-a9b9-3acafda7b8f3" class="wlWriterEditableSmartContent"><pre name="code" class="c#">        public void PlayWavResourceYield(string s)
        {
            if (player == null)
                return;

            if (inPlay &amp;&amp; soundsToPlay.Count &lt; 5)
            {
                soundsToPlay.Enqueue(s);
                return;
            }

            PlaySound(s);
        }
</pre></div><p>
If the application is currently playing a media file then the request is placed on
queue for later playback otherwise the sound will be played. If the media file is
requested for the first time ten it will be asynchronously downloaded, added to the
available media list then played.
</p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ebef9bbf-7910-446f-b440-e2ea6ebbb0d6" class="wlWriterEditableSmartContent"><pre name="code" class="c#">        private void PlaySound(string resourceName)
        {
            var mediaFile = GetMediaFileFromResourceName(resourceName);

            lock (media)
            {
                if (media.ContainsKey(mediaFile) == false)
                {
                    var wc = new WebClient();
                    wc.OpenReadCompleted += delegate(object sender, OpenReadCompletedEventArgs e)
                                                {
                                                    lock (media)
                                                    {
                                                        if (media.ContainsKey(mediaFile) != false) return;
                                                        media.Add(mediaFile, e.Result);
                                                        player.SetSource(e.Result);
                                                    }
                                                };
                    wc.OpenReadAsync(new Uri(mediaFile, UriKind.Relative));
                    return;
                }
            }

            var sound = media[mediaFile];
            if (sound == null) return;
            if (sound.CanSeek) sound.Position = 0;
            player.SetSource(sound);
        }</pre></div><p>
If the media file is requested again then the version available in the media list
will be reused and played to the user. 
</p><h2>Summary
</h2><p>
In summary when looking Silverlight applications one aim is to improve the perceived
user performance by:
</p><ul><li>
Quick Feedback – Provide quick feedback to the user so that the can interact with
application. Small initial xap file allowed the “Smash Canvas” and initial introduction
message where played without the overhead of other resources. 
</li><li>
Thinking Asynchronously - Performing actions asynchronously so that the user action
is not blocked while necessary processing is occurring.  Requesting media on
demand allowed content to played as needed. 
</li><li>
Separating The Application – Look at architecting the application so that it can be
split into different parts that can be managed independently if required. Using separated
code/media files allows for further expansion points and hosting options.</li></ul><img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=cacc676a-6f06-41e3-a412-aa31dbe0e74e" /><xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/N5nMJ05AA-o" height="1" width="1" /></body>
      <title>Silverlight BabySmash Performance – The Asynchronous Story</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,cacc676a-6f06-41e3-a412-aa31dbe0e74e.aspx</guid>
      <link>http://www.garchibald.com/blog/2008/11/16/SilverlightBabySmashPerformanceTheAsynchronousStory.aspx</link>
      <pubDate>Sun, 16 Nov 2008 09:07:56 GMT</pubDate>
      <description>&lt;h2&gt;Overview
&lt;/h2&gt;
&lt;p&gt;
In this blog entry I will cover some the factors effecting perceived performance and
the asynchronous code used to optimise the user experience. 
&lt;/p&gt;
&lt;h2&gt;Introduction
&lt;/h2&gt;
&lt;p&gt;
When looking at the performance of the BabySmash Silverlight application it was important
to look at a number of factors to help improve the perceived performance of the application.
These included:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Initial download size. 
&lt;li&gt;
Use of a secondary assembly. 
&lt;li&gt;
Use of media files. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So let's start of by profiling the current application see what has been done.
&lt;/p&gt;
&lt;p&gt;
&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="HttpProfile" border="0" alt="Http Download Profile" src="http://www.garchibald.com/images/Silverlight-BabySmash-Performance-The-Asynchronous-Story/HttpProfile.jpg" width="584" height="509" usemap="#httpProfileMap"&gt;
&lt;/p&gt;
&lt;map id="httpProfileMap" name="httpProfileMap"&gt;
&lt;area href="#InitialDownload" shape="rect" alt="Initial Download" coords="11,306,145,336"&gt;
&lt;area href="#InitialDownload" shape="rect" alt="Initial Download" coords="9,384,211,410"&gt;
&lt;area href="#SecondaryDownload" shape="rect" alt="Secondary Download" coords="203,309,359,340"&gt;
&lt;area href="#SecondaryDownload" shape="rect" alt="Secondary Download" coords="9,409,249,434"&gt;
&lt;area href="#LoadOnDemand" shape="rect" alt="Load On Demand" coords="434,310,571,337"&gt;
&lt;area href="#LoadOnDemand" shape="rect" alt="Load On Demand" coords="10,433,248,500"&gt;&lt;/map&gt; 
&lt;p&gt;
Looking at the HTTP profile of the application there are three distinct phases:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Synchronous download of the &lt;a href="#InitialDownload"&gt;initial html code and the Silverlight
application&lt;/a&gt;. 
&lt;li&gt;
Asynchronous download of &lt;a href="#SecondaryDownload"&gt;secondary components&lt;/a&gt;. 
&lt;li&gt;
Asynchronous download of media files &lt;a href="#LoadOnDemand"&gt;on demand&lt;/a&gt; as the
user presses keys.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;strong&gt;&lt;a name="InitialDownload"&gt;Initial Download&lt;/a&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
The default.htm file together with the initial BabySmashWeb.xap combined are around
60kb. This xap file contains all the code necessary to interact with the user, request
the additional resources and log information to the central ADO.Net Data Service.
&lt;/p&gt;
&lt;p&gt;
Using this approach the loading phase of the the Silverlight application is very short
and the user immediately shown the “Smash Canvas” as quickly a possible. 
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:22d65f87-7d80-4eb5-bc08-843aa888e09b" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;    &amp;lt;div id="silverlightControlHost"&amp;gt;
        &amp;lt;object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"&amp;gt;
            &amp;lt;param name="source" value="ClientBin/BabySmashWeb.xap"/&amp;gt;
            &amp;lt;param name="onerror" value="onSilverlightError" /&amp;gt;
            &amp;lt;param name="background" value="white" /&amp;gt;
            &amp;lt;param name="minRuntimeVersion" value="2.0.31005.0" /&amp;gt;
            &amp;lt;param name="autoUpgrade" value="true" /&amp;gt;
            &amp;lt;param name="initParams" value="logKeys=true" /&amp;gt;
            &amp;lt;a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"&amp;gt;
	            &amp;lt;img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/&amp;gt;
            &amp;lt;/a&amp;gt;
        &amp;lt;/object&amp;gt;
        &amp;lt;iframe style='visibility:hidden;height:0;width:0;border:0px'&amp;gt;&amp;lt;/iframe&amp;gt;
    &amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;a name="SecondaryDownload"&gt;Secondary Download&lt;/a&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Once the application is loaded, the constructor of the main code behind Page class
is called
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:da725dfa-9c2c-4a24-b70a-275649cd0c34" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;        public Page()
        {
            InitializeComponent();

            var controller = new Controller();
            controller.Launch();
            mainPage = controller.Windows[0];

            KeyUp += new KeyEventHandler(Page_KeyUp);

            LayoutRoot.Children.Add(mainPage);
        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Which calls starts a Controller class, which in turn starts the asynchronous requests
for the letters and the initial media file.
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:76737be7-54a5-4b40-ad54-5f6f0d8e4f3f" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;       public void Launch()
       {
           CheckForUpdatesAsync();

           SetupInitialWindowState();

           //here to pre-cache letter
           CoolLetter.InitLetterStateAsync();

           //Startup sound
           audio.PlayWavResourceYield(".Resources.Sounds." + "EditedJackPlaysBabySmash.wav");
       }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
The rest of this section will discuss how the letters stored in the secondary BabySmashEnglishLetters.xap
are downloaded and stored for use when the user presses a key. The initial technique
for loading the audio files is discussed in the implementation of PlayWavResourceYeild
in the &lt;a href="#LoadOnDemand"&gt;Load On Demand&lt;/a&gt; section below.
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:932969bf-421c-471a-8558-bd25b5be91e1" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;   public partial class CoolLetter 
	{
      public CoolLetter()
      {
         this.InitializeComponent();
      }

	    static readonly Dictionary&amp;lt;string, string&amp;gt; _letters = InitLetters();

        public static void InitLetterStateAsync()
        {
            // No work to do as the private _letters will be initialised above
        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
The InitLetters method is called by the .Net Framework when the static class is initialised.
The method utilises a WebClient class instance to asynchronously download the required
secondary assembly 
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:bff9f2e3-9797-4af9-ab96-5f74854e1d31" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;       private static Dictionary&amp;lt;string, string&amp;gt; InitLetters()
       {
           var addressUri = new Uri("BabySmashEnglishLetters.xap", UriKind.Relative);
           var letterLoader = new WebClient();
           letterLoader.OpenReadCompleted += letterAssemblyLoaded;
           letterLoader.OpenReadAsync(addressUri);
           return new Dictionary&amp;lt;string, string&amp;gt;();
       }&lt;/pre&gt;
&lt;/div&gt;
&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Once the asynchronous call is completed, reflection is used to dynamically call the
GenerateAlphanumericCharacters method of the AlphaNumericLetterGenerator class. 
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9c10caac-a8aa-4b39-a4e7-bdcc75f94798" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;	    private static void letterAssemblyLoaded(object sender, OpenReadCompletedEventArgs e)
	    {
	        if ((e.Error != null) || e.Cancelled) return;

	        // Convert the downloaded stream into an assembly
	        var a = LoadAssemblyFromXap("BabySmashLetters.dll", e.Result);

	        var generator = a.CreateInstance("BabySmashLetters.AlphaNumericLetterGenerator");

	        if (generator == null) return;


	        var generated = generator.GetType().InvokeMember("GenerateAlpanumericCharacters", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, generator,null) as Dictionary&amp;lt;string, string&amp;gt;;
            if ( generated == null ) return;
	        foreach (var pair in generated)
	        {
	            _letters.Add(pair.Key, pair.Value);
	        }
	    }
&lt;/pre&gt;
&lt;/div&gt;
Loading the assembly is achieved by extracting the requested assembly from the xap
stream as follows.&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9ae34c5c-eaa7-4c91-8d41-7aabae51e5ec" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;	    public static Assembly LoadAssemblyFromXap(string relativeUriString, Stream xapPackageStream)
        {
            var uri = new Uri(relativeUriString, UriKind.Relative);
            var xapPackageSri = new StreamResourceInfo(xapPackageStream, null);
            var assemblySri = Application.GetResourceStream(xapPackageSri, uri);

            var assemblyPart = new AssemblyPart();
            var a = assemblyPart.Load(assemblySri.Stream);
            return a;
        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;&lt;a name="LoadOnDemand"&gt;Load On Demand&lt;/a&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
By the time that the third stage of load on demand media files is reached the main
application is loaded, the secondary assembly is loading or loaded and the introduction
sound file has played. This has resulted in the download of around 160kb of files
and kept the time wait time for the user to a minimum.
&lt;/p&gt;
&lt;p&gt;
Loading the external dependencies has also given us the following advantages:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Allow for the possibility of localising the application to other non-english languages. 
&lt;li&gt;
Allow media files to be updated independently of the compiled code. 
&lt;li&gt;
Allow the media files to to be sourced from alternative locations e.g. File stored
locally on the client computer. 
&lt;li&gt;
Reduced bandwidth from 406kb for users that visit the page but do not start using
the application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The process for loading the additional media files is similar to the process to load
the assembly secondary xap file but has the additional complexity that the user can
be pressing keys very quickly. As a result the application needs to respond very quickly
by queuing the key requests then asynchronously downloading and playing the associated
sound file.
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:92cbb09d-e85b-4e5e-a9b9-3acafda7b8f3" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;        public void PlayWavResourceYield(string s)
        {
            if (player == null)
                return;

            if (inPlay &amp;amp;&amp;amp; soundsToPlay.Count &amp;lt; 5)
            {
                soundsToPlay.Enqueue(s);
                return;
            }

            PlaySound(s);
        }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
If the application is currently playing a media file then the request is placed on
queue for later playback otherwise the sound will be played. If the media file is
requested for the first time ten it will be asynchronously downloaded, added to the
available media list then played.
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ebef9bbf-7910-446f-b440-e2ea6ebbb0d6" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;        private void PlaySound(string resourceName)
        {
            var mediaFile = GetMediaFileFromResourceName(resourceName);

            lock (media)
            {
                if (media.ContainsKey(mediaFile) == false)
                {
                    var wc = new WebClient();
                    wc.OpenReadCompleted += delegate(object sender, OpenReadCompletedEventArgs e)
                                                {
                                                    lock (media)
                                                    {
                                                        if (media.ContainsKey(mediaFile) != false) return;
                                                        media.Add(mediaFile, e.Result);
                                                        player.SetSource(e.Result);
                                                    }
                                                };
                    wc.OpenReadAsync(new Uri(mediaFile, UriKind.Relative));
                    return;
                }
            }

            var sound = media[mediaFile];
            if (sound == null) return;
            if (sound.CanSeek) sound.Position = 0;
            player.SetSource(sound);
        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
If the media file is requested again then the version available in the media list
will be reused and played to the user. 
&lt;/p&gt;
&lt;h2&gt;Summary
&lt;/h2&gt;
&lt;p&gt;
In summary when looking Silverlight applications one aim is to improve the perceived
user performance by:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Quick Feedback – Provide quick feedback to the user so that the can interact with
application. Small initial xap file allowed the “Smash Canvas” and initial introduction
message where played without the overhead of other resources. 
&lt;li&gt;
Thinking Asynchronously - Performing actions asynchronously so that the user action
is not blocked while necessary processing is occurring.&amp;nbsp; Requesting media on
demand allowed content to played as needed. 
&lt;li&gt;
Separating The Application – Look at architecting the application so that it can be
split into different parts that can be managed independently if required. Using separated
code/media files allows for further expansion points and hosting options.&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=cacc676a-6f06-41e3-a412-aa31dbe0e74e" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,cacc676a-6f06-41e3-a412-aa31dbe0e74e.aspx</comments>
      <category>babysmash</category>
      <category>silverlight</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=cf06e539-fcf2-406a-8406-428fc846372c</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,cf06e539-fcf2-406a-8406-428fc846372c.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,cf06e539-fcf2-406a-8406-428fc846372c.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cf06e539-fcf2-406a-8406-428fc846372c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Well Scott Hanselman has delivered his session at <a href="http://www.hanselman.com/blog/PDCMicrosoftNETFrameworkOverviewAndApplicationsForBabies.aspx">PDC
NET Framework: Overview and Applications for Babies</a>. And from the tweet streams
it looks like he had a full room and fantastic feedback.
</p>
        <p>
As Scott indicated in his earlier blog post he covers a <a href="http://www.hanselman.com/blog/PDC2008BabySmashPreparations.aspx">lot
of content</a> in a short space of time so I would suggest watching the recorded video
of his session TL49 <strike>(once it becomes available at </strike><a href="http://channel9.msdn.com"><strike>http://channel9.msdn.com</strike></a><strike> in
the next 24 hours)</strike> that is now online from <a href="http://channel9.msdn.com/pdc2008/TL49/">Channel9</a> or
download the WMV file <a href="http://mschnlnine.vo.llnwd.net/d1/pdc08/WMV-HQ/TL49.wmv">directly</a> for
offline viewing.
</p>
        <p>
As an overview Scott’s presentation included different variants of his original WPF
full framework  <a href="http://www.babysmash.com">BabySmash</a> application
expanded to use different platforms &amp; technologies i.e.
</p>
        <ul>
          <li>
BabySmash Surface PC Demo. 
</li>
          <li>
BabySmash WPF application using MEF. 
</li>
          <li>
ADO.Net Data Service. 
</li>
          <li>
Windows Mobile Running Silverlight 2 BabySmash. 
</li>
          <li>
ASP.Net Charting. 
</li>
          <li>
ASP.NET MVC Charting. 
</li>
          <li>
BabySmash running under Silverlight 2 in the Browser. 
</li>
          <li>
Silverlight 2 Charting.</li>
        </ul>
        <p>
Scott ended the presentation by sending the address to the Silverlight version out
to twitter users. As users hit the keys, the results were sent to the ADO.Net Data
Service which then displayed the live results using a Silverlight Chart and Microsoft
Virtual earth.
</p>
        <p>
This is where my involvement started. Scott decided to use initial port of BabySmash
to Silverlight that I created in his PDC presentation, to deliver on the MMO (Massively
Multiplayer Online) request for BabySmash.
</p>
        <p>
So the BabySmash Silverlight MMO PDC version was born so to speak. Now that Scott
has publically demonstrated the Silverlight version, I will continue adding blog posts
to my existing <a href="http://www.garchibald.com/babysmash">BabySmash</a> series.
In the new posts I will discuss further details of the Silverlight version of BabySmash
and the Silverlight Reporting that Scott and I collaborated upon to create the final
result for the presentation.
</p>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=cf06e539-fcf2-406a-8406-428fc846372c" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/QW22WoW6Kj8" height="1" width="1" /></body>
      <title>BabySmash At PDC</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,cf06e539-fcf2-406a-8406-428fc846372c.aspx</guid>
      <link>http://www.garchibald.com/blog/2008/10/28/BabySmashAtPDC.aspx</link>
      <pubDate>Tue, 28 Oct 2008 06:47:41 GMT</pubDate>
      <description>&lt;p&gt;
Well Scott Hanselman has delivered his session at &lt;a href="http://www.hanselman.com/blog/PDCMicrosoftNETFrameworkOverviewAndApplicationsForBabies.aspx"&gt;PDC
NET Framework: Overview and Applications for Babies&lt;/a&gt;. And from the tweet streams
it looks like he had a full room and fantastic feedback.
&lt;/p&gt;
&lt;p&gt;
As Scott indicated in his earlier blog post he covers a &lt;a href="http://www.hanselman.com/blog/PDC2008BabySmashPreparations.aspx"&gt;lot
of content&lt;/a&gt; in a short space of time so I would suggest watching the recorded video
of his session TL49 &lt;strike&gt;(once it becomes available at &lt;/strike&gt;&lt;a href="http://channel9.msdn.com"&gt;&lt;strike&gt;http://channel9.msdn.com&lt;/strike&gt;&lt;/a&gt;&lt;strike&gt; in
the next 24 hours)&lt;/strike&gt; that is now online from &lt;a href="http://channel9.msdn.com/pdc2008/TL49/"&gt;Channel9&lt;/a&gt; or
download the WMV file &lt;a href="http://mschnlnine.vo.llnwd.net/d1/pdc08/WMV-HQ/TL49.wmv"&gt;directly&lt;/a&gt; for
offline viewing.
&lt;/p&gt;
&lt;p&gt;
As an overview Scott’s presentation included different variants of his original WPF
full framework&amp;nbsp; &lt;a href="http://www.babysmash.com"&gt;BabySmash&lt;/a&gt; application
expanded to use different platforms &amp;amp; technologies i.e.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
BabySmash Surface PC Demo. 
&lt;li&gt;
BabySmash WPF application using MEF. 
&lt;li&gt;
ADO.Net Data Service. 
&lt;li&gt;
Windows Mobile Running Silverlight 2 BabySmash. 
&lt;li&gt;
ASP.Net Charting. 
&lt;li&gt;
ASP.NET MVC Charting. 
&lt;li&gt;
BabySmash running under Silverlight 2 in the Browser. 
&lt;li&gt;
Silverlight 2 Charting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Scott ended the presentation by sending the address to the Silverlight version out
to twitter users. As users hit the keys, the results were sent to the ADO.Net Data
Service which then displayed the live results using a Silverlight Chart and Microsoft
Virtual earth.
&lt;/p&gt;
&lt;p&gt;
This is where my involvement started. Scott decided to use initial port of BabySmash
to Silverlight that I created in his PDC presentation, to deliver on the MMO (Massively
Multiplayer Online) request for BabySmash.
&lt;/p&gt;
&lt;p&gt;
So the BabySmash Silverlight MMO PDC version was born so to speak. Now that Scott
has publically demonstrated the Silverlight version, I will continue adding blog posts
to my existing &lt;a href="http://www.garchibald.com/babysmash"&gt;BabySmash&lt;/a&gt; series.
In the new posts I will discuss further details of the Silverlight version of BabySmash
and the Silverlight Reporting that Scott and I collaborated upon to create the final
result for the presentation.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=cf06e539-fcf2-406a-8406-428fc846372c" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,cf06e539-fcf2-406a-8406-428fc846372c.aspx</comments>
      <category>babysmash</category>
      <category>pdc</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=58b62c20-c431-45b2-8719-d4f86940b63d</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,58b62c20-c431-45b2-8719-d4f86940b63d.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,58b62c20-c431-45b2-8719-d4f86940b63d.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=58b62c20-c431-45b2-8719-d4f86940b63d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Windows Azure has just been announced at PDC 2008. And information is now available
online from <a href="http://www.microsoft.com/azure/default.mspx">http://www.microsoft.com/azure/default.mspx</a>.
</p>
        <p>
Drilling into the features for developers there is a video interview with <a href="mms://mschnlnine.wmod.llnwd.net/a1809/d1/ch9/9/4/5/4/3/4/SteveMarxRedDogForDevelopers_s_ch9.wmv">Steve
Marx</a> that outlines Azure from a developer perspective:
</p>
        <ul>
          <li>
His blog <a title="http://blog.smarx.com/default.aspx" href="http://blog.smarx.com/default.aspx">http://blog.smarx.com/default.aspx</a> hosted
on Windows Azure. 
</li>
          <li>
Aim to use current skills and technology that they are used to. Built around .Net
I.e. 
<ul><li>
Use Visual Studio 
</li><li>
.Net 3.5 
</li><li>
IIS 7 
</li><li>
Windows Communication Foundation</li></ul></li>
          <li>
Only difference is that it runs on the cloud or Fabric of components. 
</li>
          <li>
Client side local development experience to test before deployment 
<ul><li>
Azure API's 
</li><li>
Debugging 
</li><li>
Ability to emulate Simulate scale via Visualised Compute. 
</li><li>
Synchronised state 
</li><li>
Azure storage available (Blobs, Tables)</li></ul></li>
          <li>
Deployment, VS.Net deploy package and configuration file to a web portal. 
</li>
          <li>
Question about management:</li>
          <ul>
            <li>
Framework will restart application is required 
</li>
            <li>
Logging and metering 
</li>
            <li>
Integration with Windows Live Alerts to send information about service 
</li>
            <li>
Ability to deploy new versions seamlessly</li>
          </ul>
          <li>
Ability to set metrics "e.g. Queue length, response time" to trigger scale out. 
</li>
          <li>
Ability to scale out on demand if required (IIS and SQL Services). 
</li>
          <li>
Currently in CTP. 
</li>
          <li>
Programming Differences</li>
          <ul>
            <li>
Horizontal Scale - Store state centralised so that it can be accessed by any machine
in the virtual web farm</li>
            <ul>
              <li>
e.g. Web Farm - Save shopping cart 
</li>
            </ul>
            <li>
Using in blob or table helps eliminate bottlenecks of centralised SQL Server for persistence
of state.</li>
          </ul>
          <li>
Ability to create services that can be leveraged buy other users e.g. Email service
gateway. 
</li>
          <li>
Service Discovery, still determine plans about how create Market Place of services
over the next Year e.g.</li>
          <ul>
            <li>
Find Services 
</li>
            <li>
What do they cost 
</li>
            <li>
Ratings for services 
</li>
            <li>
Ability to integrate services in the development environment</li>
          </ul>
          <li>
Technology</li>
          <ul>
            <li>
RESTful interface 
</li>
            <li>
Manages &amp; Unmanaged Code 
</li>
            <li>
Can be used from Python, Ruby etc</li>
          </ul>
          <li>
Does not have to be web form applications could just be a REST interface to a headless
service.</li>
        </ul>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=58b62c20-c431-45b2-8719-d4f86940b63d" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/zpvVHYhnE9U" height="1" width="1" /></body>
      <title>Windows Azure For Developers</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,58b62c20-c431-45b2-8719-d4f86940b63d.aspx</guid>
      <link>http://www.garchibald.com/blog/2008/10/27/WindowsAzureForDevelopers.aspx</link>
      <pubDate>Mon, 27 Oct 2008 17:48:06 GMT</pubDate>
      <description>&lt;p&gt;
Windows Azure has just been announced at PDC 2008. And information is now available
online from &lt;a href="http://www.microsoft.com/azure/default.mspx"&gt;http://www.microsoft.com/azure/default.mspx&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Drilling into the features for developers there is a video interview with &lt;a href="mms://mschnlnine.wmod.llnwd.net/a1809/d1/ch9/9/4/5/4/3/4/SteveMarxRedDogForDevelopers_s_ch9.wmv"&gt;Steve
Marx&lt;/a&gt; that outlines Azure from a developer perspective:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
His blog &lt;a title="http://blog.smarx.com/default.aspx" href="http://blog.smarx.com/default.aspx"&gt;http://blog.smarx.com/default.aspx&lt;/a&gt; hosted
on Windows Azure. 
&lt;/li&gt;
&lt;li&gt;
Aim to use current skills and technology that they are used to. Built around .Net
I.e. 
&lt;ul&gt;
&lt;li&gt;
Use Visual Studio 
&lt;/li&gt;
&lt;li&gt;
.Net 3.5 
&lt;/li&gt;
&lt;li&gt;
IIS 7 
&lt;/li&gt;
&lt;li&gt;
Windows Communication Foundation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Only difference is that it runs on the cloud or Fabric of components. 
&lt;/li&gt;
&lt;li&gt;
Client side local development experience to test before deployment 
&lt;ul&gt;
&lt;li&gt;
Azure API's 
&lt;/li&gt;
&lt;li&gt;
Debugging 
&lt;/li&gt;
&lt;li&gt;
Ability to emulate Simulate scale via Visualised Compute. 
&lt;/li&gt;
&lt;li&gt;
Synchronised state 
&lt;/li&gt;
&lt;li&gt;
Azure storage available (Blobs, Tables)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Deployment, VS.Net deploy package and configuration file to a web portal. 
&lt;/li&gt;
&lt;li&gt;
Question about management:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
Framework will restart application is required 
&lt;/li&gt;
&lt;li&gt;
Logging and metering 
&lt;/li&gt;
&lt;li&gt;
Integration with Windows Live Alerts to send information about service 
&lt;/li&gt;
&lt;li&gt;
Ability to deploy new versions seamlessly&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Ability to set metrics "e.g. Queue length, response time" to trigger scale out. 
&lt;/li&gt;
&lt;li&gt;
Ability to scale out on demand if required (IIS and SQL Services). 
&lt;/li&gt;
&lt;li&gt;
Currently in CTP. 
&lt;/li&gt;
&lt;li&gt;
Programming Differences&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
Horizontal Scale - Store state centralised so that it can be accessed by any machine
in the virtual web farm&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
e.g. Web Farm - Save shopping cart 
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Using in blob or table helps eliminate bottlenecks of centralised SQL Server for persistence
of state.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Ability to create services that can be leveraged buy other users e.g. Email service
gateway. 
&lt;/li&gt;
&lt;li&gt;
Service Discovery, still determine plans about how create Market Place of services
over the next Year e.g.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
Find Services 
&lt;/li&gt;
&lt;li&gt;
What do they cost 
&lt;/li&gt;
&lt;li&gt;
Ratings for services 
&lt;/li&gt;
&lt;li&gt;
Ability to integrate services in the development environment&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Technology&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
RESTful interface 
&lt;/li&gt;
&lt;li&gt;
Manages &amp;amp; Unmanaged Code 
&lt;/li&gt;
&lt;li&gt;
Can be used from Python, Ruby etc&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Does not have to be web form applications could just be a REST interface to a headless
service.&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=58b62c20-c431-45b2-8719-d4f86940b63d" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,58b62c20-c431-45b2-8719-d4f86940b63d.aspx</comments>
      <category>azure</category>
      <category>pdc</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=e8fadd67-072d-4c79-83ba-d1f85a4e7968</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,e8fadd67-072d-4c79-83ba-d1f85a4e7968.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,e8fadd67-072d-4c79-83ba-d1f85a4e7968.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=e8fadd67-072d-4c79-83ba-d1f85a4e7968</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This <a href="http://webdesign.meetup.com/108/calendar/8542022/">months web meetup</a> showcased
the new features of IE 8 Beta 2 presented by Matt Heller from Microsoft and Firefox
3.1 Beta 1 by <a href="http://weblogs.mozillazine.org/roc/">Robert O'Callahan</a> and <a href="http://www.bluishcoder.co.nz/">Chris
Double</a> from Mozilla.<br /></p>
        <p>
        </p>
        <h3>IE 8 Beta 2
</h3>
        <p>
        </p>
        <p>
Matt was first up he covered the following:
</p>
        <ul>
          <li>
CSS 2.1 improvements. 
</li>
          <li>
Accelerators formally Activities in Beta 1 (Examples <a title="http://www.ieaddons.com/en/accelerators/" href="http://www.ieaddons.com/en/accelerators/">http://www.ieaddons.com/en/accelerators/</a>). 
</li>
          <li>
Web Slices (Examples <a title="http://www.ieaddons.com/en/webslices/" href="http://www.ieaddons.com/en/webslices/">http://www.ieaddons.com/en/webslices/</a>). 
</li>
          <li>
User interface improvements such as <a href="http://lifehacker.com/5042941/internet-explorer-8-beta-2s-familiar-new-features">Smart
Address Bar, Tab Grouping</a>. 
</li>
          <li>
Compatibility view in toolbar - <a href="http://blogs.msdn.com/ie/archive/2008/08/27/introducing-compatibility-view.aspx">More
information</a> available in the IE 8 team blog. 
</li>
          <li>
Quick demo of the <a href="http://blogs.msdn.com/ie/archive/2008/09/03/developer-tools-in-internet-explorer-8-beta-2.aspx">developer
tool bar</a>. 
</li>
          <li>
Aspects of HTML 5 support e.g. history, DOM storage, network connectivity events. 
<br /></li>
        </ul>
        <p>
For those wanting to take the new Beta or old versions of IE for a test drive Microsoft
Virtual PC images are available for <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef&amp;displaylang=en">download</a>. 
<br /></p>
        <p>
        </p>
        <h3>Firefox 3.1 Beta 1 
<br /></h3>
        <p>
Next up to present were Robert and Chris. Robert has a great <a href="http://weblogs.mozillazine.org/roc/archives/2008/09/auckland_web_me_1.html">post
on his blog</a> about how he saw the meeting. He includes a copy of his slide deck
and some demo pages that currently work with the daily build of Firefox 3.1 Beta 1. 
<br /></p>
        <p>
The video and svg demonstration were of particular interest as it showed equivalent
functionality to what Silverlight 1.0 offered, but without the need for a separate
plug-in that needed to be installed. As Robert indicated in a recent <a href="http://weblogs.mozillazine.org/roc/archives/2008/08/why_ogg_matters.html">post</a> Mozilla
has elected to use the Ogg Vorbis/Theora codecs for audio and video. With support
for H.264 currently in Flash and announced that H.264 will be available in a future
version  of Silverlight, it will be interesting to see how widespread the use
of Ogg and Theora will become. 
<br /></p>
        <p>
For those interested Chris has uploaded a couple videos to YouTube <a href="http://www.youtube.com/watch?v=vvtdkxCIKC8">Firefox
Video Element Bling</a> and <a href="http://www.youtube.com/watch?v=Har-PRP4X9U&amp;feature=related">SVG
Video Demo</a> that demonstrate the new HTML 5 video and SVG features inside the current
Firefox 3.1 Beta 1 available which is for <a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/">download</a>.
As this a Beta release Mozilla suggest setting up a separate profile for testing side
by side using the -ProfileManager command line switch. 
<br /></p>
        <p>
        </p>
        <h3>Take away thoughts 
<br /></h3>
        <ul>
          <li>
Support for parts of HTML5 and CSS3 are being released from multiple vendors. 
</li>
          <li>
Hosting of media files for Ogg/Thora may pose issues for users without the equivalent
YouTube/Silverlight Streaming services. 
</li>
          <li>
JIT compiled javascript code has the possibility to deliver much faster experience
to the end user. 
</li>
          <li>
Much more competition between plug-in's (Flash, Silverlight) and embedded browser
functionality coming up.</li>
        </ul>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=e8fadd67-072d-4c79-83ba-d1f85a4e7968" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/6qfNoJiiDgI" height="1" width="1" /></body>
      <title>IE8 Beta 2 and Firefox 3.1 Beta 1</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,e8fadd67-072d-4c79-83ba-d1f85a4e7968.aspx</guid>
      <link>http://www.garchibald.com/blog/2008/09/17/IE8Beta2AndFirefox31Beta1.aspx</link>
      <pubDate>Wed, 17 Sep 2008 08:17:44 GMT</pubDate>
      <description> &lt;p&gt;
This &lt;a href="http://webdesign.meetup.com/108/calendar/8542022/"&gt;months web meetup&lt;/a&gt; showcased
the new features of IE 8 Beta 2 presented by Matt Heller from Microsoft and Firefox
3.1 Beta 1 by &lt;a href="http://weblogs.mozillazine.org/roc/"&gt;Robert O'Callahan&lt;/a&gt; and &lt;a href="http://www.bluishcoder.co.nz/"&gt;Chris
Double&lt;/a&gt; from Mozilla.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h3&gt;IE 8 Beta 2
&lt;/h3&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Matt was first up he covered the following:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
CSS 2.1 improvements. 
&lt;/li&gt;
&lt;li&gt;
Accelerators formally Activities in Beta 1 (Examples &lt;a title="http://www.ieaddons.com/en/accelerators/" href="http://www.ieaddons.com/en/accelerators/"&gt;http://www.ieaddons.com/en/accelerators/&lt;/a&gt;). 
&lt;/li&gt;
&lt;li&gt;
Web Slices (Examples &lt;a title="http://www.ieaddons.com/en/webslices/" href="http://www.ieaddons.com/en/webslices/"&gt;http://www.ieaddons.com/en/webslices/&lt;/a&gt;). 
&lt;/li&gt;
&lt;li&gt;
User interface improvements such as &lt;a href="http://lifehacker.com/5042941/internet-explorer-8-beta-2s-familiar-new-features"&gt;Smart
Address Bar, Tab Grouping&lt;/a&gt;. 
&lt;/li&gt;
&lt;li&gt;
Compatibility view in toolbar - &lt;a href="http://blogs.msdn.com/ie/archive/2008/08/27/introducing-compatibility-view.aspx"&gt;More
information&lt;/a&gt; available in the IE 8 team blog. 
&lt;/li&gt;
&lt;li&gt;
Quick demo of the &lt;a href="http://blogs.msdn.com/ie/archive/2008/09/03/developer-tools-in-internet-explorer-8-beta-2.aspx"&gt;developer
tool bar&lt;/a&gt;. 
&lt;/li&gt;
&lt;li&gt;
Aspects of HTML 5 support e.g. history, DOM storage, network connectivity events. 
&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
For those wanting to take the new Beta or old versions of IE for a test drive Microsoft
Virtual PC images are available for &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef&amp;amp;displaylang=en"&gt;download&lt;/a&gt;. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h3&gt;Firefox 3.1 Beta 1 
&lt;br&gt;
&lt;/h3&gt;
&lt;p&gt;
Next up to present were Robert and Chris. Robert has a great &lt;a href="http://weblogs.mozillazine.org/roc/archives/2008/09/auckland_web_me_1.html"&gt;post
on his blog&lt;/a&gt; about how he saw the meeting. He includes a copy of his slide deck
and some demo pages that currently work with the daily build of Firefox 3.1 Beta 1. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
The video and svg demonstration were of particular interest as it showed equivalent
functionality to what Silverlight 1.0 offered, but without the need for a separate
plug-in that needed to be installed. As Robert indicated in a recent &lt;a href="http://weblogs.mozillazine.org/roc/archives/2008/08/why_ogg_matters.html"&gt;post&lt;/a&gt; Mozilla
has elected to use the Ogg Vorbis/Theora codecs for audio and video. With support
for H.264 currently in Flash and announced that H.264 will be available in a future
version&amp;nbsp; of Silverlight, it will be interesting to see how widespread the use
of Ogg and Theora will become. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
For those interested Chris has uploaded a couple videos to YouTube &lt;a href="http://www.youtube.com/watch?v=vvtdkxCIKC8"&gt;Firefox
Video Element Bling&lt;/a&gt; and &lt;a href="http://www.youtube.com/watch?v=Har-PRP4X9U&amp;amp;feature=related"&gt;SVG
Video Demo&lt;/a&gt; that demonstrate the new HTML 5 video and SVG features inside the current
Firefox 3.1 Beta 1 available which is for &lt;a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/"&gt;download&lt;/a&gt;.
As this a Beta release Mozilla suggest setting up a separate profile for testing side
by side using the -ProfileManager command line switch. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h3&gt;Take away thoughts 
&lt;br&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
Support for parts of HTML5 and CSS3 are being released from multiple vendors. 
&lt;/li&gt;
&lt;li&gt;
Hosting of media files for Ogg/Thora may pose issues for users without the equivalent
YouTube/Silverlight Streaming services. 
&lt;/li&gt;
&lt;li&gt;
JIT compiled javascript code has the possibility to deliver much faster experience
to the end user. 
&lt;/li&gt;
&lt;li&gt;
Much more competition between plug-in's (Flash, Silverlight) and embedded browser
functionality coming up.&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=e8fadd67-072d-4c79-83ba-d1f85a4e7968" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,e8fadd67-072d-4c79-83ba-d1f85a4e7968.aspx</comments>
      <category>browser</category>
    </item>
    <item>
      <trackback:ping>http://www.garchibald.com/blog/Trackback.aspx?guid=2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3</trackback:ping>
      <pingback:server>http://www.garchibald.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.garchibald.com/blog/PermaLink,guid,2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3.aspx</pingback:target>
      <dc:creator>Grant Archibald</dc:creator>
      <wfw:comment>http://www.garchibald.com/blog/CommentView,guid,2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3.aspx</wfw:comment>
      <wfw:commentRss>http://www.garchibald.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In this post I will briefly discuss using Google Analytics in conjunction with Silverlight,
to track the version installed and your application usage patterns.
</p>
        <p>
Following on from Nikhil Kothari's blog entry on <a href="http://www.nikhilk.net/Silverlight-Analytics.aspx">Tracking
Silverlight-enabled Browsers via Analytics</a> I have made a few tweaks to the original
JavaScript that can be placed at the end of your HTML document after pageTracker has
been initialised to provide for the following.
</p>
        <ul>
          <li>
A change from the old <b>__utmSetVar</b> function in the urchin.js tracking to the
new <strong>pageTracker._setVar</strong> in ga.js version for the following <a href="http://www.roirevolution.com/blog/2008/01/should_you_join_the_migration_urchinjs_migrates_to.html">reasons</a>. 
</li>
          <li>
A check for Linux to distinguish between Moonlight usage versus Silverlight.</li>
        </ul>
        <p>
Based on this information it may help you further refine your Silverlight strategy
based on your visitors e.g.
</p>
        <ul>
          <li>
The split in visitor numbers between Silverlight Version 1 or 2. Important in terms
of:<br /><ul><li>
Install experience. 
</li><li>
Documentation on why the user should upgrade (Features/Differences). 
</li><li>
What messages should be displayed to the user of an older Version 1.0 client. 
</li><li>
Compatibility with the upcoming <a href="http://silverlight.net/learn/mobile.aspx">Silverlight
1.0 for Mobile</a> which will initially only support Version 1.</li></ul></li>
          <li>
Determine the cross platform use of your application. 
</li>
          <li>
The possible need to cater for font availability across different operating systems.</li>
        </ul>
        <p>
Also as indicated in the comments of Nikhil's blog post Jeff Wilcox has a great post <a href="http://blogs.msdn.com/jeffwilcox/archive/2007/10/01/using-google-analytics-with-rich-managed-web-applications-in-silverlight.aspx">Using
Google Analytics with rich (managed) web applications in Silverlight</a> that explores
how to integrate tracking within your Silverlight application.
</p>
        <!-- code formatted by http://manoli.net/csharpformat/ -->
        <div class="csharpcode">
          <pre class="alt">
            <span class="kwrd">&lt;</span>
            <span class="html">script</span>
            <span class="attr">type</span>
            <span class="kwrd">="text/javascript"</span>
            <span class="kwrd">&gt;</span>
          </pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">function</span> getSilverlightVersion() {</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">var</span> version = <span class="str">''</span>;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">var</span> container = <span class="kwrd">null</span>;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">try</span> {</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">var</span> control = <span class="kwrd">null</span>;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">var</span> product = <span class="str">'Silverlight'</span>;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> ( navigator.userAgent.indexOf(<span class="str">"Linux"</span>)!=-1)
product=<span class="str">"Moonlight"</span>;</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> (window.ActiveXObject) {</pre>
          <pre> </pre>
          <pre class="alt">            control = <span class="kwrd">new</span> ActiveXObject(<span class="str">'AgControl.AgControl'</span>);</pre>
          <pre> </pre>
          <pre class="alt">        }</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">else</span> {</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> (navigator.plugins[<span class="str">'Silverlight
Plug-In'</span>]) {</pre>
          <pre> </pre>
          <pre class="alt">                container = document.createElement(<span class="str">'div'</span>);</pre>
          <pre> </pre>
          <pre class="alt">                document.body.appendChild(container);</pre>
          <pre> </pre>
          <pre class="alt">                container.innerHTML= <span class="str">'&lt;embed
type="application/x-silverlight" src="data:," /&gt;'</span>;</pre>
          <pre> </pre>
          <pre class="alt">                control = container.childNodes[0];</pre>
          <pre> </pre>
          <pre class="alt">            }</pre>
          <pre> </pre>
          <pre class="alt">        }</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> (control) {</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> (control.isVersionSupported(<span class="str">'2.0'</span>))
{ version = product + <span class="str">'/2.0'</span>; }</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">else</span>
            <span class="kwrd">if</span> (control.isVersionSupported(<span class="str">'1.0'</span>))
{ version = product + <span class="str">'/1.0'</span>; }</pre>
          <pre> </pre>
          <pre class="alt">        }</pre>
          <pre> </pre>
          <pre class="alt">    }</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">catch</span> (e) { }</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> (container) {</pre>
          <pre> </pre>
          <pre class="alt">        document.body.removeChild(container);</pre>
          <pre> </pre>
          <pre class="alt">    }</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">return</span> version;</pre>
          <pre> </pre>
          <pre class="alt">}</pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">if</span> ( pageTracker )</pre>
          <pre> </pre>
          <pre class="alt">    pageTracker._setVar(getSilverlightVersion()); </pre>
          <pre> </pre>
          <pre class="alt">
            <span class="kwrd">&lt;/</span>
            <span class="html">script</span>
            <span class="kwrd">&gt;</span>
          </pre>
        </div>
        <img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3" />
      <xhtml:img xmlns:xhtml="http://www.w3.org/1999/xhtml" src="http://feeds.feedburner.com/~r/grantarchibald/~4/8th-Wf4GnXc" height="1" width="1" /></body>
      <title>Tracking Silverlight And Moonlight Enabled Browsers via Google Analytics</title>
      <guid isPermaLink="false">http://www.garchibald.com/blog/PermaLink,guid,2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3.aspx</guid>
      <link>http://www.garchibald.com/blog/2008/08/10/TrackingSilverlightAndMoonlightEnabledBrowsersViaGoogleAnalytics.aspx</link>
      <pubDate>Sun, 10 Aug 2008 10:16:20 GMT</pubDate>
      <description>&lt;p&gt;
In this post I will briefly discuss using Google Analytics in conjunction with Silverlight,
to track the version installed and your application usage patterns.
&lt;/p&gt;
&lt;p&gt;
Following on from Nikhil Kothari's blog entry on &lt;a href="http://www.nikhilk.net/Silverlight-Analytics.aspx"&gt;Tracking
Silverlight-enabled Browsers via Analytics&lt;/a&gt; I have made a few tweaks to the original
JavaScript that can be placed at the end of your HTML document after pageTracker has
been initialised to provide for the following.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
A change from the old &lt;b&gt;__utmSetVar&lt;/b&gt; function in the urchin.js tracking to the
new &lt;strong&gt;pageTracker._setVar&lt;/strong&gt; in ga.js version for the following &lt;a href="http://www.roirevolution.com/blog/2008/01/should_you_join_the_migration_urchinjs_migrates_to.html"&gt;reasons&lt;/a&gt;. 
&lt;/li&gt;
&lt;li&gt;
A check for Linux to distinguish between Moonlight usage versus Silverlight.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Based on this information it may help you further refine your Silverlight strategy
based on your visitors e.g.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The split in visitor numbers between Silverlight Version 1 or 2. Important in terms
of:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
Install experience. 
&lt;/li&gt;
&lt;li&gt;
Documentation on why the user should upgrade (Features/Differences). 
&lt;/li&gt;
&lt;li&gt;
What messages should be displayed to the user of an older Version 1.0 client. 
&lt;/li&gt;
&lt;li&gt;
Compatibility with the upcoming &lt;a href="http://silverlight.net/learn/mobile.aspx"&gt;Silverlight
1.0 for Mobile&lt;/a&gt; which will initially only support Version 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Determine the cross platform use of your application. 
&lt;/li&gt;
&lt;li&gt;
The possible need to cater for font availability across different operating systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Also as indicated in the comments of Nikhil's blog post Jeff Wilcox has a great post &lt;a href="http://blogs.msdn.com/jeffwilcox/archive/2007/10/01/using-google-analytics-with-rich-managed-web-applications-in-silverlight.aspx"&gt;Using
Google Analytics with rich (managed) web applications in Silverlight&lt;/a&gt; that explores
how to integrate tracking within your Silverlight application.
&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/javascript"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; getSilverlightVersion() {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;var&lt;/span&gt; version = &lt;span class="str"&gt;''&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;var&lt;/span&gt; container = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;try&lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;var&lt;/span&gt; control = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;var&lt;/span&gt; product = &lt;span class="str"&gt;'Silverlight'&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; ( navigator.userAgent.indexOf(&lt;span class="str"&gt;"Linux"&lt;/span&gt;)!=-1)
product=&lt;span class="str"&gt;"Moonlight"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (window.ActiveXObject) {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;            control = &lt;span class="kwrd"&gt;new&lt;/span&gt; ActiveXObject(&lt;span class="str"&gt;'AgControl.AgControl'&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (navigator.plugins[&lt;span class="str"&gt;'Silverlight
Plug-In'&lt;/span&gt;]) {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;                container = document.createElement(&lt;span class="str"&gt;'div'&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;                document.body.appendChild(container);&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;                container.innerHTML= &lt;span class="str"&gt;'&amp;lt;embed
type="application/x-silverlight" src="data:," /&amp;gt;'&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;                control = container.childNodes[0];&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;            }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (control) {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (control.isVersionSupported(&lt;span class="str"&gt;'2.0'&lt;/span&gt;))
{ version = product + &lt;span class="str"&gt;'/2.0'&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (control.isVersionSupported(&lt;span class="str"&gt;'1.0'&lt;/span&gt;))
{ version = product + &lt;span class="str"&gt;'/1.0'&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (e) { }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (container) {&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;        document.body.removeChild(container);&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    }&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; version;&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; ( pageTracker )&lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;    pageTracker._setVar(getSilverlightVersion()); &lt;/pre&gt;
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.garchibald.com/blog/aggbug.ashx?id=2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3" /&gt;</description>
      <comments>http://www.garchibald.com/blog/CommentView,guid,2d6f03d3-aab7-451f-ae76-1ee8abf3c5c3.aspx</comments>
      <category>moonlight</category>
      <category>silverlight</category>
    </item>
  </channel>
</rss>
