LA.NET [EN]

Apr 30

Silverlight: simplifying the FilmStrip sample

Posted in Silverlight      Comments Off on Silverlight: simplifying the FilmStrip sample

Today I”ve started looking at the samples that accompany Silverlight. I started with the FilmStrip sample. After looking at it for some minutes, I thought that maybe I could simplify the code needed to achieve the image transitions. If you look at the original code, you”ll see that there are several storyboards that set up each transition. you”ll also see that they”re really duplicates and that the only thing that changes is the value of the Value property applied to the SplineDoubleKeyFrame element. In fact, if you pay attention to the storyboards, you”ll see that each storyboard decreases (or increases, depending on the direction you follow 🙂 ,,) the value by 1024.

So, what”s happening here is that these extra lines of XAML (for each transition) could be reduced to one storyboard whose value is changed during the click of the next/previous button. To achieve this, you should start by removing all the extra storyboards and kepp only one. In my case, I”ve ended up with this xaml (i”m only putting the inner loadedRoot canva”s triggers xaml):

<Canvas.Triggers>
 <EventTrigger RoutedEvent=”Canvas.Loaded”>
  <EventTrigger.Actions>
    <BeginStoryboard>
       <Storyboard BeginTime=”5″ Duration=”00:00:01″ x:Name=”story”>
             <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X”  Storyboard.TargetName=”slideX1″>
                <SplineDoubleKeyFrame
                       Name=”anim1″
                       KeySpline=”0.7,0,0.4,1″ Value=”0″ KeyTime=”00:00:00.8″/>
           </DoubleAnimationUsingKeyFrames>
          <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX2″>
                <SplineDoubleKeyFrame
                     Name=”anim2″
                     KeySpline=”0.7,0,0.4,1″ Value=”1024″ KeyTime=”00:00:00.8″/>
           </DoubleAnimationUsingKeyFrames>
          <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX3″>
                <SplineDoubleKeyFrame
                    Name=”anim3″
                    KeySpline=”0.7,0,0.4,1″ Value=”2048″ KeyTime=”00:00:00.8″/>
         </DoubleAnimationUsingKeyFrames>
         <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX4″>
              <SplineDoubleKeyFrame
                  Name=”anim4″ 
                  KeySpline=”0.7,0,0.4,1″ Value=”3072″ KeyTime=”00:00:00.8″/>
         </DoubleAnimationUsingKeyFrames>
         <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX5″>
             <SplineDoubleKeyFrame
                Name=”anim5″
                KeySpline=”0.7,0,0.4,1″ Value=”4096″ KeyTime=”00:00:00.8″/>
       </DoubleAnimationUsingKeyFrames>
       <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX6″>
          <SplineDoubleKeyFrame
              Name=”anim6″
              KeySpline=”0.7,0,0.4,1″ Value=”5120″ KeyTime=”00:00:00.8″/>
       </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX7″>
         <SplineDoubleKeyFrame
             Name=”anim7″ 
              KeySpline=”0.7,0,0.4,1″ Value=”6144″ KeyTime=”00:00:00.8″/>
      </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames BeginTime=”00:00:00″ Storyboard.TargetProperty=”X” Storyboard.TargetName=”slideX8″>
          <SplineDoubleKeyFrame
               Name=”anim8″ 
               KeySpline=”0.7,0,0.4,1″ Value=”7168″ KeyTime=”00:00:00.8″/>
       </DoubleAnimationUsingKeyFrames>
     </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
 </EventTrigger>
</Canvas.Triggers>

As you can see, I”ve changed the name of the storyboard to story and I”ve named each of the SplineDoubleKeyFrame so that we can change its Value during each button click. As I”ve said, in the initial sample each storyboard would be an exact copy of the previous: the only thing that changes is the value of Value property (and this value is decremented by 1024 in each element). With this knowledge, we just need to build a function that increments or decrements each of the animation by the necessary factor:

function updateAnims( factor ){
   for( var i = 1; i < 9; i++ ){
        wpfe.findName( “anim” + i ).Value = wpfe.findName( “anim” + i ).Value – factor;
   }
}

Changing the upForward method to use the new strategy is really simple:

function upForward (s,e) {
  if (currentSlide < 8) {
     currentSlide++;
     var factor = 1024;
     updateAnims( factor );
     wpfe.findName(“story”).Begin();
     if (currentSlide < 8) {
        wpfe.findNa
me(“forwardButton”).fill = “#FF000000”
        wpfe.findName(“forwardButton”).stroke = “#FFAAAAAA”
    }
    else {
        wpfe.findName(“forwardButton”).fill = “#FF000000”
        wpfe.findName(“forwardButton”).stroke = “#FF222222”
    }
  }
  wpfe.findName(“backButton”).fill = “#FF000000”
  wpfe.findName(“backButton”).stroke = “#FFAAAAAA”
}

All that is needed is to update the animations before running them (this is only possible because the animation retains its final value after beeing run). You”ll also need to change the upBack method so that it updates the animation values with negative values:

//….previous code removed
currentSlide–;
var factor = 1024;
updateAnims( -factor );

wpfe.findName(“story”).begin();

While performing these changes, I”ve also noticed that each image is downloaded through its own Downloader object, which also seemed a waste of resources. After looking at the docs, it seemed like I couldn”t use only one downloader for all the images because loading ad image could only be done by setting a path or associating a Downloader with it. I though that if I associated a downloader with an Image and then downloaded a second image with the same downloader, that isecond mage would be rendered in the associated Image control (ie, i thought that callluing the SetSource method would result in creating a binding between the Image and the Downloader). Since I didn”t find any way to explicitly set the bytes of the image, I thought that those extra-Downloader objects were really necessary. Even though it seemed like I was wasting time, I”ve changed the code so that it only used one downloader. The first thing I did was create a global method with the following code:

function __getDownloader(){
  if( downloader == null ){
      downloader = wpfe.createObject(“Downloader”);
      downloader.downloadProgressChanged = “javascript:downloadProgressChanged”
      downloader.completed = “javascript:downloadCompleted”
  }
  return downloader;
}

And the, I”ve replaced these lines (in the downloadAssets and downloadCompleted methods):

downloader = wpfe.createObject(“Downloader”);
downloader.downloadProgressChanged = “javascript:downloadProgressChanged”
downloader.completed = “javascript:downloadCompleted”;

with this one:

downloader = __getDownloader();

After opening the page in the browser, I though that I”d get the last picture eight times. But that didn”t happen…it worked, ie, using a single Downloader was more than enough to get all the images…So, it seemed like this sample was a little “bloated” after all…