Jesse Liberty - Silverlight Geek

By, For and About Silverlight Developers
Tutorial Feedback – Leave a Comment Why Dontcha?

I’m incredibly pleased to say that we have implemented a comments section for each tutorial, just as we do for each video

Tutorial Comments

Please leave your comments and I will subscribe to the comments list and try to respond as quickly as possible (if your comment goes unanswered for a while, don’t hesitate to send me mail: jliberty@microsoft.com

NB: I’ve heard loud and clear that you want to see more advanced topics covered; they are on the way. The current plan calls for a tutorial in September and one in October and then to look at the frequency; either staying at once a month or bumping it up to twice a month. I’m traveling for some of September so will let you know shortly after that.

 

Thanks!

From-To Animation vs. Linear Keyframe

In much of the writing about animation in Silverlight, one question that seems to  recur is this: why bother with a linear key-frame animation if it is less intuitive and more complex than a simple from-to animation

Let’s back up and examine that for just a second.

Linear Interpolation

Linear Interpolation means that if you instruct the animation to start at position 0 and move to position 200 over 4 seconds, then you know that it will be at position 100 at 2 seconds, (half way there in half the time) and at position 50 at 1 second (1/4 of the way in 1/4 of the time) and at position 25 at 1/2 second. That is, the distance is covered evenly over the allotted time.

It turns out that there are two types of animation in Silverlight that use linear interpolation: simple from-to animation, and Linear Keyframe animation.

From-To Animation

From-to animation just says “Take this value and change its value from x to y over this much time”.  For example, you might write

<DoubleAnimation Storyboard.TargetName=”TT1” Storyboard.TargetProperty=”X”
From=”0” To=”500” Duration=”0:0:2” />

DoubleAnimation means that you’re going to create an animation by changing some value that is expressed as a Double (that is a number that might have a fraction).

The Target is named TT1 (in this case it is a Transform but it could be a shape, etc.)  The property on that target is X (in this case the X position in an (X,Y) point.  Then you see the From value (0) and the To value (500) and the Duration (2 seconds) which means that you’re going to change that property (x) from 0 to 500 over 2 seconds.

A From To Example

Suppose you want to move a rectangle from the upper left to the lower right of your control, and you’re writing the Xaml by hand. One very easy way to do so is to use From-to animation (specifically, a DoubleAnimation that targets the Rectangle’s TranslateTransform X and Y). You might end up with a Page.xaml that looks like this:

   1: <UserControl x:Class="BlogAnimationExample.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     Width="600" Height="800">
   5:     <UserControl.Resources>
   6:         <Storyboard x:Name="FT1">
   7:             <DoubleAnimation 
   8:             Storyboard.TargetName="TT1"
   9:             Storyboard.TargetProperty="X"
  10:             From="0" To="500" Duration="0:0:2" />
  11:             <DoubleAnimation 
  12:             Storyboard.TargetName="TT1"
  13:             Storyboard.TargetProperty="Y"
  14:             From="0" To="700" Duration="0:0:2" />
  15:         </Storyboard>
  16:  
  17:     </UserControl.Resources>
  18:     <Grid x:Name="LayoutRoot" Background="White"  >
  19:         <Rectangle x:Name="rect1" 
  20:             HorizontalAlignment="Left" 
  21:             VerticalAlignment="Top"
  22:             Margin="10,0,0,0" 
  23:             Stroke="#FFFF0000" 
  24:             Width="200" Height="60">
  25:             <Rectangle.RenderTransform>
  26:                 <TransformGroup>
  27:                     <TranslateTransform x:Name="TT1"  />
  28:                 </TransformGroup>
  29:             </Rectangle.RenderTransform>
  30:         </Rectangle>
  31:     </Grid>
  32: </UserControl>

 

 

 

 

 

 

You need something to kick that off, so modify Page.xaml.cs as follows:

   1: public Page()
   2: {
   3:    InitializeComponent();
   4:    Loaded += new RoutedEventHandler( Page_Loaded );
   5: }
   6:  
   7: void Page_Loaded( object sender, RoutedEventArgs e )
   8: {
   9:    FT1.Begin();
  10: }

 

Now the animation will begin as soon as the page loads.

Adding a Wrinkle

That works fine, but what if instead of having the rectangle drift to the lower right on an angle, what you’d like is for the rectangle to go straight down, then to the right and then return home on the angle?

If you look at our story board you can see that it is combining the first DoubleAnimation that moves to the right with the second animation that moves down to create a single path that moves down and to the right at the same time. What is needed is three story boards!

   1: <UserControl.Resources>
   2:     <Storyboard x:Name="FT1">
   3:         <!--Move down-->
   4:         <DoubleAnimation 
   5:         Storyboard.TargetName="TT1"
   6:         Storyboard.TargetProperty="Y"
   7:         From="0" To="700" Duration="0:0:2" />
   8:      </Storyboard>
   9:     <Storyboard x:Name="FT2">
  10:         <!--Move right-->
  11:         <DoubleAnimation 
  12:         Storyboard.TargetName="TT1"
  13:         Storyboard.TargetProperty="X"
  14:         From="0" To="500" Duration="0:0:2" />
  15:     </Storyboard>
  16:     <Storyboard x:Name="FT3">
  17:         <!--Move home-->
  18:         <DoubleAnimation 
  19:         Storyboard.TargetName="TT1"
  20:         Storyboard.TargetProperty="X"
  21:         From="500" To="0" Duration="0:0:2" />
  22:         <DoubleAnimation
  23:         Storyboard.TargetName="TT1"
  24:         Storyboard.TargetProperty="Y"
  25:         From="700" To="0" Duration="0:0:2" />
  26:     </Storyboard>
  27: </UserControl.Resources>

The first storyboard moves down (and not to the right), the second moves right, and the third moves both on both the x and y axis to move home. Unfortunately, you’re not done. Because of multi-tasking you can’t just launch these; you have to make sure that FT1 has completed before you start FT2, and that must complete in turn before you launch FT3.

Fortunately, there is a completed event for storyboards, so it isn’t all that difficult:

   1: public Page()
   2: {
   3:    InitializeComponent();
   4:    Loaded += new RoutedEventHandler( Page_Loaded );
   5:    FT1.Completed += new EventHandler( FT1_Completed );
   6:    FT2.Completed += new EventHandler( FT2_Completed );
   7: }
   8:  
   9: void FT2_Completed( object sender, EventArgs e )
  10: {
  11:    FT3.Begin();
  12: }
  13:  
  14: void FT1_Completed( object sender, EventArgs e )
  15: {
  16:    FT2.Begin();
  17: }
  18:  
  19: void Page_Loaded( object sender, RoutedEventArgs e )
  20: {
  21:    FT1.Begin();
  22: }

It isn’t pretty, but it works.

Using Keyframes

 

 

 

Keyframes give you a good bit more control at the cost of a little more complexity. With Keyframes you state a series of time/value pairs.

So rather than just saying here’s my start value and my end value and how much time you have you say at time 0 the value is 0 and at time 1 second it is 120 and at time 1.27 seconds it is 195 and at time 2 seconds it is 400.

You can have as many time elements as you want, and they don’t have to be evenly spaced. While the system will create a linear interpolation between the values you supply, you do not have to space your explicitly named values evenly. So it is perfectly legitimate to tell the shape to move 50 units in the first second, 200 units in the next two seconds and 500 units in the fourth second.

That extra power allows you to solve the problem above with a single storyboard:

   1: <UserControl.Resources>
   2:     <Storyboard x:Name="StoryBoard1" >
   3:         <DoubleAnimationUsingKeyFrames 
   4:         Storyboard.TargetName="TT1"
   5:         Storyboard.TargetProperty="X">
   6:             <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0" />
   7:             <LinearDoubleKeyFrame KeyTime="0:0:2" Value="0" />
   8:             <LinearDoubleKeyFrame KeyTime="0:0:4" Value="500" />
   9:             <LinearDoubleKeyFrame KeyTime="0:0:6" Value="0" />
  10:         </DoubleAnimationUsingKeyFrames>
  11:         <DoubleAnimationUsingKeyFrames 
  12:         Storyboard.TargetName="TT1"
  13:         Storyboard.TargetProperty="Y">
  14:             <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0" />
  15:             <LinearDoubleKeyFrame KeyTime="0:0:2" Value="700" />
  16:             <LinearDoubleKeyFrame KeyTime="0:0:4" Value="700" />
  17:             <LinearDoubleKeyFrame KeyTime="0:0:6" Value="0" />
  18:         </DoubleAnimationUsingKeyFrames>
  19:     </Storyboard>
  20: </UserControl.Resources>
  21: <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="false
  22:     <Rectangle x:Name="rect1" 
  23:     HorizontalAlignment="Left" 
  24:     VerticalAlignment="Top" 
  25:     Margin="10,0,0,10" 
  26:     Stroke="#FFFF0000" 
  27:     Width="200" 
  28:     Height="60" >
  29:         <Rectangle.RenderTransform>
  30:             <TransformGroup>
  31:                 <ScaleTransform   />
  32:                 <RotateTransform  />
  33:                 <TranslateTransform x:Name="TT1"  />
  34:             </TransformGroup>
  35:         </Rectangle.RenderTransform>
  36:     </Rectangle>
  37: </Grid>

 

 

 

 

Because the keyframe allows me to hold the Y value in place after I move it, I can wait there while I move right, creating my own synchronization as needed without creating multiple storyboards, and giving a much cleaner, easier to understand and maintain animation.

More on this soon.

Four Transforms

I haven’t really written much about transforms in a long while. We looked at them in depth during the Silverlight 1.0 time frame and then more or less took them for granted ever since.

It may be time for a review – perhaps a quick video (it’s on my list!). In the meantime, here’s a quick peak into some of what we say about Transforms in our forthcoming book,  [footnote 1]

Programming Silverlight 2
by Jesse Liberty, Tim Heuer

Read more about this title...
A Transform is just a change

A transform is just an instruction in Xaml to change the object in a particular way, and wouldn’t be interesting, except that you can have that change happen to your object either when that object is in a “state” (e.g., mouseOver) or as part of an animation (“move from here to there and get twice as big over the next 5 seconds”). In that case, the ability to specify all that in Xaml (as opposed to code) really is quite interesting.

Playing With Transforms

To see some of this in action, create a project in Expression Blend and create four rows and 2 columns of approximately equal size (or, if like me, you have OCD, put the design surface in split mode and set the column and row sizes exactly.

Once you’re done admiring your grid, draw a circle in the upper left cell (hold the shift key while you draw an ellipse.)  In the properties window set its name to Circle1 and set its Width and Height to 90, its alignments to center and its margins to zero. Fill it with a nice blue. Then make 3 more circles, filling the upper two rows, giving each circle its own color.

Fill the bottom two rows with rectangles sized 120 by 80, also centered in each cell with no margin. Take a moment to name the circles Circle1, Circle2, etc. and the rectangles Rect1, Rect2, etc. and give them each a distinct color.

When you are done, your grid should look more or less like this,

StartingGrid

 

Click on the first circle (you can click on Circle1 in the Objects and Timeline window) and open the Transform tab in the Properties window. Notice that the Transform Window has six tabs, if you hover over each in turn they are identified as

  • · Translate
  • · Rotate
  • · Scale
  • · Skew
  • · Center Point
  • · Flip
Translate

A TranslateTransform moves the object. Set the X value to 225 and the Y value to 125. Suddenly your circle is visiting with the red circle that was down and to the right. You have “translated” its 0,0 position to a new position in the grid.

Rotate

No surprise what this does. Click on the rectangle in the lower left corner and then click on the rotate tab. You are prompted to enter an angle; enter the value 45 and watch the rectangle swivel 45 degrees as shown here

AfterRotateWithArrows

Scale

As you would expect, scale lets you grow or shrink an object. Let’s set the scale of the green rectangle to 1.5 and of the purple rectangle to .5, and finally, let’s set the yellow rectangle’s X scale to 1.5 and its Y scale to .5. Finally, let’s scale the X and Y of the purple circle up by 1.5 but with the green, let’s scale the X up by 1.5 but leave the Y alone. The result is shown here,

 Scaled

 

Restore

Before we look at Skew translations we need to restore the circles and rectangles to their original sizes and shapes. To do so, click each shape in turn and then look at the RenderTransform label in the Transform window. You’ll see a small white dot indicating that the object has been transformed. Click on that dot as shown here,

AdvancedPropertyOptions

This will bring up the Advanced Property Options Dialog, the first choice of which is Reset; click on this to reset all the transforms for this object. Do this for each of the shapes in turn; they will each be restored to their starting size, shape and orientation.

Skew

A skew changes the lines of an objects along its x or y axis and can either distort the apparent slope of an object (e.g., turning a square into a parallelogram) or can even simulate three dimensions.

Replace the rectangles with 80 by 80 squares. Let’s skew the first (left-most) one by setting its X value to 45 and its Center (the next tab to the right) to 0,0.

Skew45

 

 

y45-05Ctr


 

 

You can combine skewing on one axis with changing the center to give the illusion of an object bisecting the surface of the plane. Click on the middle square and set its Y skew to 45° (thus turning the skewed figure on its side) and also set its center to 0.5, 0.5;

 

 

 

Hope that is helpful

---------------

[footnote 1 – this is just an excerpt from unedited text, placed here not to push the book but to provide what I hope will be  helpful information. The book is mentioned only because the material is copyright 2008 O'Reilly Media ]

Visual Thesaurus – Mindware

When I wasn’t looking this Website/Mindware got a lot better. Visual Thesaurus is an on-line subscription tool (~$3/month) that you can also buy as a desktop utility, that allows you to put in a word and see its related words visually. I put in play and got back a blizzard of related words,

Play

(Click on the image to see it full size)

Each node can be clicked on to find out what everything radiating from that node shares in common. For example, travel, locomote, go and move all radiate from a common node. Clicking on that brings up a definition that all four share, and an example sentence,

Node

What relationships are shown in the diagram is dictated by your settings (as is font size, line size and many other aspects of the diagram),

thesaurusSettings

You can see that this goes well beyond just synonyms.

PartsOfSpeech

 

The node colors are keyed to the definition chart (thus, the green that tied together the four words above is listed in the verbs section, and all the verb nodes in the entire diagram are defined there as well.

You can reverse the action and find a definition under verb and that will light up the node and thus show you the words associated with it.

 

IndirectNode

 

 

 

Of course, if you click on a word, that word becomes the focus of a new set of associations, allowing you to progress from Play –> Contend –> Debate –>Argument –>Variable->Symbol to Star…

sign

This can be either incredibly rewarding for your writing, or a tremendous time-sink. But it is wonderfully responsive and great fun.

Candidate for favorite new utility

I admit it, this has little to do with Silverlight per se, but it is such a useful utility, and I use it so much all day (including when I’m programming) that I thought I’d share it with you, at least briefly.

ClipTrak1

 

 

 

 

Every time you copy anything to the clip board, it is captured to ClipTrack (though you can create white and black lists to change that behavior). You can find things in chronological order, alphabetical order, by when they were clipped,by when they were pasted, by type (image, text, web, etc.) or you can create folders (favorites, project based, whatever). You can look at web pages in html view, text view or web view, and modify before re-saving or pasting.  It just goes on and on.

ClipTrakUpperLeft



Area 1 has the menu (which includes some powerful option settings) and four buttons: add a clip (lets you hand create text to add to the clip board), delete a clip, paste and move (move from one folder to another). 

Area 2 is the list of folders – there are pre-designed folders (by date when clipped, by date when pasted, by type (images, text, html, etc.) and also custom folders (favorites, by project, etc.). Below Area 2 in area 5 are buttons to create and delete custom folders.

ClipTrakList

Area 3 is a list of the clips in the folder you’ve picked. Each title can be changed without changing the clipping and the image to the far left indicates the type of clip.

When you highlight any clip it is displayed in area 8, and can be edited using the tools in area 6. For complex types (e.g., web pages) and you can switch your view from HTML to TExt to Web which is very nice.

ClipTrakEdit

Printing

I wrote to the author (Mark Sweeney) and asked for a feature in a future release: take whatever is the current clip and let me print it. What I had in mind was that there are times I want to copy and print something from the web that is not well formatted; I’d rather not have to paste it into a text editor and then print from there. Within a day he added the print button (area 7) that not only has print setup and print preview, but automatically defaults to “shrink to fit printed page”  along with a host of other useful features.  Truly great.

 ClipPrintPreview

 

 

 

 

Please note, the application is available through PC Magazine utilities, which is a subscription service.

Full disclosure, I was formerly employed by Ziff Davis, which was at one point the parent company of PC Mag and I was, even earlier than that, the WizOp of the PC Mag BBS but that was long ago and far away.

3 New Vids Post; 2 Move to the Top of my To-do List

I’m pleased to announce we’ve posted three new videos:

  • Graphics and Brushes (never hurts to “brush up” on the fundamentals and I try to bring together what we were doing in 1.0 with what Blend brings to the party.
  • Using Multiple Pages Part 2 covers passing data/parameters from one page to the next (and no change the the url and no callbacks because everything happens on the client
  • In-state animation – By adding just a tiny bit of animation to a control while it is within its state (while the mouse is over the control or while it has the focus) you can greatly enhance the user’s experience.

3NewVids

In the In-State Animation video I show the use of a Content Presenter control to allow the user to dynamically set the content for my round button, and in fact this is what allows me to use one template instead of four in the blog post A Third Way To Handle Templated Buttons and Images but it would be nice to show that technique in a video of its own; so that is on the way.  Therefore I’m moving up two videos:

1) How to use a contentPresenter to allow the user to set the content of a templated button and

2) How to use image resources to use one templated button with multiple backgrounds

Now on the top of my to-do list.

 

-j

A third way to handle Templated Buttons & Images

 

In yesterday’s blog post I suggested that there were two solutions to crating a templated button that used an image. One was to create a different template for each image (yuck) and the other was to create a custom temlpated button.

A third, and excellent alternative was suggested to me by email by Justin Angel, and that is to set the images as Resources in Expression Blend. Then, you can add buttons to your pages, and apply the template (which will control such things as how they behavior in response to a mouse over, and you can apply the Resource as a background.  Very nice.

Here is how I did it to get the effect I wanted.  (NB: this will all be shown in detail in a forthcoming video, and is summarized here very quickly):

  1. 1. I copied the source code from the previous project to my new project as a starting point
  2. I threw away the button templates
  3. I added four stock photos to my project and one by one added them to the design surface, and clicked on them and then selected Tools –> Make Brush Resource –> Make Brush Resource and when presented with the dialog box gave each a name, and made it an application resource…

 

Thus I ended up with four resources, each usable as a background.

4. Next I created a single template for my button, but this time instead of making a template from scratch, a made a copy of the existing template.  A little spelunking and I was able to discard the cowl that made the background hard to see, and I changed the mouse-over behavior to bounce like a silly Mac-dock entry and I modified the pressed behavior as well.

   1: <vsm:VisualState x:Name="MouseOver">
   2:     <Storyboard AutoReverse="True" RepeatBehavior="Forever">
   3:        
   4:        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
   5:           Storyboard.TargetName="Background" 
   6:             Storyboard.TargetProperty="(UIElement.RenderTransform).
   7:              (TransformGroup.Children)[3].(TranslateTransform.Y)">
   8:                 <SplineDoubleKeyFrame KeyTime="00:00:00" Value="-10"/>
   9:                 <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
  10:        </DoubleAnimationUsingKeyFrames>
  11:           <!-- you get the idea -->
  12:         <Storyboard.TargetName="CurvedBevel" 
  13:         <Storyboard.TargetName="Accent" 
  14:         <Storyboard.TargetName="contentPresenter" 
  15:     </Storyboard>
  16: </vsm:VisualState>

 

 

 

Finally, I added a stack panel to hold the buttons and added four regular buttons. For each one, I set its background to one of the resources (giving each a nice picture background) and dragged the template on (giving them all the templated changes) and then set the content (which I was able to do because buttons do have a contentPresenter) and the font, font color and font size.  The net effect was much cleaner than 4 templats and the only code that had to change at all was rewiring the 4 button event handlers.

FourButtonsWithImages

A video on all this will be forthcoming as soon as I get back from vacation.

Thanks.

Web Cast and Digging Deeper

Today I had the pleasure of presenting a web cast on building an application with more than one page and passing data among those pages. I have 2 videos on this topic, so if you missed the web cast and are interested, you may find this first video on switching pages of interest, and the second video should be posted soon.

TwoPages

 

Multi-Page In A Nutshell

The premise is that there is a third page that has no content and when it is time to display one of your pages, you make the page you want to display (which is, after all, a UserControl) the content of that third page (I’ve chosen to name the third page PageSwitcher but of course you may call it anything you like. PageSwitcher has a method, Navigate that takes a UserControl and makes whatever you pass in, its content.  The implementation for the button on each page is to make the page you are switching to the new content.

Passing Values

Because we destroy the current page when we replace it (to conserve on client-side resources) if we wish to pass information (such as the book name, authors, whether the book is published and whether or not it is fiction) the easiest way is to make PageSwitcher the temporary repository; and the most efficient way to do that is to overload the navigate method to take an Object so that you may pass in anything at all, and then fish it out when your new page is loaded (very effective, very efficient and not at all type safe!).

To see this at work, assume the user has filled out the fields as shown in Page 1 and clicked switch. The event handler for the button might look a bit like this:

void SwitchButton_Click( object sender, RoutedEventArgs e )
{
   PageSwitcher ps = this.Parent as PageSwitcher;
   if ( ps != null )
   {
      Book b = new Book();
      b.BookName = BookName.Text;
      b.Authors = Authors.Text;
      b.isPublished = IsPublished.IsChecked == true;
      b.isFiction = Fiction.IsChecked == true;
      ps.Navigate( new Page2(),b );
   }

We know that our “parent” is the PageSwitcher as we are its content, and so the cast is safe (but being good o-o programmers we check (Доверяй, но проверяй)

We then spin up a Book instance (defined off camera and fill in the properties from the user-filled in fields and then call the overloaded Navigate method, providing a new instance of Page2 and our newly filled in book.

We trust PageSwitcher to (a) abandon Page.xaml and make Page2 its content and to hold onto whatever we’ve passed it until Page2 asks for it (think Secretkeeper in Harry Potter).

When Page2 is safely established, it asks PageSwitcher if there are any little presents waiting, like this:

void Page2_Loaded( object sender, RoutedEventArgs e )
{
   PageSwitcher ps = this.Parent as PageSwitcher;
   if ( ps != null )
   {
      if ( ps.SwitcherTag != null )
      {
         Book b = ps.SwitcherTag as Book; 
         
         string isPublished = string.Empty;
         if ( b.isPublished == false)
         {
            isPublished = " not ";
         }
         string isFiction = b.isFiction ? " is Fiction " : "is non-fiction";

         BodyText.Text = "Found " + b.BookName + " written by " +
            b.Authors + ". The book is " + isPublished + " published and " + isFiction;
      }
      SwitchButton.Click += new RoutedEventHandler( SwitchButton_Click );
   }

That is, if you are my parent (and you are) do you have anything tucked away in your SwitcherTag property. (“Whats it gots in its pocketses?”) If so, I happen to know that it is a really a book object, and it is my book object and gimme.

Now all of that is fine and good but we’ve been here before. One of the viewers asked if I could show how to pick among 4 pages, and by the way could my buttons look cooler. So, instead of working on my chapter, which I really have to do, I spent the past four hours creating a new version that has bouncy buttons with images that take you to four different pages.

It’s wicked easy to do if (and only if) you are willing to make 4 templates. If you want one template, well then my friend you have to figure out how to expose not only the content property that button has, but the image source pro