Information for designers and interactive developers - Issue 2 - May 2008
home  |  articles  |  register for the newsletter  |  Issue 1  |  Issue 3  |  Issue 4  |  Issue 5  |  Issue 6
The Designer Role - Part 2
Level: Intermediate

Creating enhanced User Experiences with Windows Presentation Foundation is similar to designing User Experiences for the web, yet different in many aspects as well. In this article we explore these factors and discuss some best practices for designers creating WPF projects in perfect synchronization with the developers.

System Requirements: Microsoft Expression Blend 1.0 or later
In the previous installment, we talked about how designers play a critical role in the development cycle of a software project, and the various methods that can be used for working with a software development team that works completely outside of the design area.

This time we are going to go past the theories and get our hands dirty with some very specific, practical examples: an animated image button, skinning an entire application, and protecting your intellectual property. So let's jump right in.

Animated Image Button
Our goal here is to create a clickable image that can be used as a button. On the web or in other interactive design tools you can usually do this by dragging an image on to the design surface and either hyperlinking it or converting it to a button. As we discussed in the previous part, the Tools Menu > Make Button command does exactly that in Expression Blend. However, to design for a software application, you have to think a bit like a developer. Let's see why.

If you take an image and use the Make Button command, the following Style code will be generated:

    6 <Style x:Key="ButtonStyle1" BasedOn="{x:Null}" TargetType="{x:Type Button}">

    7             <Setter Property="Template">

    8                 <Setter.Value>

    9                     <ControlTemplate TargetType="{x:Type Button}">

   10                         <Grid>

   11                             <Image Source="ImageFile.png" Stretch="Fill"/>

   12                             <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>

   13                         </Grid>

   14                         <ControlTemplate.Triggers>

   15                             <Trigger Property="IsFocused" Value="True"/>

   16                             <Trigger Property="IsDefaulted" Value="True"/>

   17                             <Trigger Property="IsMouseOver" Value="True"/>

   18                             <Trigger Property="IsPressed" Value="True"/>

   19                             <Trigger Property="IsEnabled" Value="False"/>

   20                         </ControlTemplate.Triggers>

   21                     </ControlTemplate>

   22                 </Setter.Value>

   23             </Setter>

   24         </Style>


An average application can have more than two dozen such buttons. So that equals almost 240 lines of code. And everything in those 24 Styles will be the same except the name of the image. And at the end of the day that is unnecessary burden on the application. The key here is reusability. What we will do is create a single custom ControlTemplate and reuse it for all buttons.
  • Start a fresh new WPF Application project in Blend.
  • Import an image that can be used as a button. Use Project > Add Existing Item (or Ctrl+I)
  • Create a simple Button control on your Window1 design surface. Size or placement is not important here. We will now use this Button to create our own ControlTemplate.
  • Right-click on the Button and select Edit Control Parts (Template) > Create Empty. You can also access this via the Object menu.
  • You will now see the Create ControlTemplate Resource dialog.
  • Enter "AnimatedButton" (or whatever name you like), and select Application in the Define in selection. You can optionally also select an existing ResourceDictionary or create a new one. In fact, it is highly recommended. You can see the previous installment of this article for details.
  • Click OK
The basic skeleton of our new Animated Button is now complete. But before we start adding animated image buttons to our application, we need to create the animation Timelines. For the purposes of this exercise, we will animate the opacity of the image to show the Idle and MouseOver states of the button.
  • After you click OK in the Create ControlTemplate Resource dialog, you will be taken to the Template editing mode. Switch to Animation Workspace mode through the Window menu.
  • Let's create our basic "idle" or default state of the button. The state currently being edited is the highlighted one in the Triggers panel on the bottom left. Since we have not created any new states the Default state should be selected.

  • Select the ContentPresenter control from the Asset Library. Double-click the icon to create a ContentPresenter with default settings (always more useful than creating one by dragging or drawing).

  • Select the ContentPresenter in the Objects and Timelines panel.
  • Go to the Properties panel on the right and change the Opacity to 70%. The default state will be slightly transparent so the "OnMouseOver" state can create the illusion of glowing.
We have now created our default state. Now we need the MouseOver and MouseOut timelines to create the entire animation, and to fire them.
  • Click the Add Property Trigger button in the Triggers panel.
  • A new trigger will now appear. By default it should be set to the IsDefault property.
  • In the Properties when active panel right underneath the trigger, select Target-Element in the first dropdown and IsMouseOver in the second dropdown.
  • Type "true" in the textbox right next to the dropdowns.
  • In the Objects and Timelines panel, click the New button (a small plus sign).

  • In the Create Storyboard Resource dialog, enter a name for our new Timeline. Let's call this one "MouseOver".
  • You will now see a Timeline appear. Drag the Current Time slider (a long vertical yellow bar) to the time position 0:00.300.
  • With the ContentPresenter selected, change the Opacity property to 100%.
When you complete Step 8 above, a new keyframe will be created for the Opacity property of the ContentPresenter. Unlike other interactive design tools, Blend only needs a keyframe when a property changes to the final value. Since you can run parallel timelines in WPF, the "start" value of the animation will be automatically grabbed and changed (over the course of the timeline) to the new value therefore erasing the need to have a keyframe at the start of a timeline. If you find this somewhat confusing, wait till the end of this exercise and we will see first-hand the value of this feature.
  • Let's create the MouseOut timeline now. This will be exactly like creating the MouseOver timeline.
  • Create a new timeline and name it "MouseOut".
  • Go to the time position 0:00.600. We'll stretch the "out" animation a bit for effect.
  • Select the ContentPresenter and set its opacity to 70% - the same value as our idle state. However, since the default is already 70%, a keyframe won't be created. So drag the Opacity slider back or forth a bit and then rest it on 70% - this will force the keyframe to be created.
Our timelines are now ready. All we need to do is attach them to the button's Events. Thanks to Blend this can be done completely in the UI without having to write any code.

  • Select the trigger entry that says IsMouseOver = True
  • In the bottom panel that says Actions when activating, add a new action by clicking the small plus sign.
  • A new action entry will be created in the panel. Select MouseOver and Begin in the two dropdowns.
  • In the other panel that says Actions when deactivating, click the Add New Action button and select MouseOut and Begin in the new action entry.
  • Double-click anywhere on the design area (except for yellow-highlighted template area) to exit to Window level.
Our work is done. The AnimatedButton template is now ready. Let's see how we can use this template:
  • Make sure you are out of the Template Editing mode. Delete the existing button.
  • Make a new button of default size by double-clicking the Button tool in the toolbox.
  • 3Right-click the button and select Edit Control Parts > Apply Resource > AnimatedButton. This will inherit the new ControlTemplate we created.
  • Double-click the new button in the design view.
  • With the new button select, go to the Project panel and right-click one of the images you imported. Select the Insert menu command.
  • A new Image object should be placed inside the button.
  • Exit the button selection by double-clicking anywhere on the design area.
  • Hit F5 to test the project.
If you mouse over the button in the running application, you will see a MouseOver and MouseOut animation! Repeat the same process shown above to create more buttons. You can place different images inside each button.


What we have done is create a main template for the animation and states and it is being reused throughout the application. If you open app.xaml or the ResourceDictionary where you placed the template, you will see that only one piece of code is required no matter how many buttons you make.

For a more realistic and usable button, you will need other states like IsEnabled, IsFocused, IsDefault, Down, and others. A good place to learn more about them is to use Edit Control Parts > Edit a Copy on a default button or use the Simple Styles we talked about in the previous part.

You can get the code for such the complete animated button template, and a non-animated version of this template that uses only Triggers instead of Timelines on my blog.

Before we move forward, let's see the big advantage of parallel timelines and intelligent keyframes. When you hover over the button, the opacity goes from 70% to 100%, and when you take the cursor off the button, it goes back to 100%. But if take the cursor away before the MouseOver timeline completes, i.e. the opacity goes to 100%, say something like 83%, the MouseOut timeline will fire but it won't start from 100% to 70% like it would in most animation packages, it will take the current value of 83% and go back to 70% from there. Such parallel timelines and intelligent keyframes help avoid jerky animations like you often see on the web.

To further see this in action, change the default to 10% instead of 70%, and move the keyframes in both timelines from 0:00.300 to 0:02.00, and then try it out.

Skinning an application with Named Brushes
In the previous installment, we talked about creating a complete skin or theme for an application by using ResourceDictionaries. We also looked at the theme example of SimpleStyles. While visually the SimpleStyles theme appears very simple and not-so-sophisticated, it is however a perfect system to build your own themes upon. Creating themes for each and every control type falls out of the scope of this particular article and every designer will use their own techniques to build ControlTemplates. So what we will discuss instead is a very important point to keep in mind when creating your skin.

Even if all the elements of your controls use the color #FF000000 (Web Developers, note that the first 2 digits represent the Alpha/Opacity of the color, not the Red value), you should not hardcode or set the color manually for each control. You should create a Brush resource and reuse it throughout the theme.

To create a Brush resource:
  • Create a Rectangle or any graphic shape.
  • Change its Fill property to a color or gradient that you want the Brush resource to be.
  • Right under the Color Palette, select the + Brush (Convert Brush to Resource) button.
  • Enter a name for the Brush resource and place it in your ResourceDictionary.
  • The rectangle can now be deleted.
To apply the Brush resource:
  • Create a shape or control that you want to apply the Brush resource to. A rectangle is adequate.
  • Go to the Fill property of the object.
  • Select the last tab above the Fill Color Palette that says Brush Resources.
  • Select the Brush resource you want and it will be applied to the control.
The Brush resource created previously will now be applied to your new grapic.

The importance of this is that changing a single brush (you can do that via the Resources panel) changes the entire theme! Below are two sample images of a full theme created using named Brush resources. You can see many of the brushes in the Resources panel. The first screenshot shows the default look. The second screenshot shows the new look created by changing only the MainColor brush that serves as the base for all controls.

Study SimpleStyles.xaml in the Resource panel to see how the theme uses this same structure to control the colors of the entire theme through a simple set of Brush resources. This principle is the cornerstone of theme development for WPF.

Such changeability allows the developer to change the color the theme without having to get the designer involved - this is very useful for the developers in tight deadlines. It also lets the developer create code that lets the end-user select the color they want for the application. You can see this functionality in Windows Live Messenger or Windows Media Player.

Protecting your Intellectual Property
A very important issue for designers - especially freelance consultants - is sharing the source code/XAML of their themes, designs, etc. with their clients.
One technique is to provide a DLL (Dynamic Linked Library) file instead of XAML code. This works mostly when dealing with ResourceDictionary files and is especially useful for themes.

Here is how to protect the code by building it into a DLL:
  • Create a new WPF Control Library project in Blend.
  • Delete the default UserControl1.xaml file the new project contains.
  • Go to Project menu > Add Existing Item, and add your XAML file (ResourceDictionary)
  • Build the project from Project Menu > Build Solution (Ctrl + Shift + B)
In your project's folder, inside the BIN folder, you will have a new DLL file (it should be the same name as your project). This DLL contains the XAML in a compiled format that can't be directly read by a human.

Using the ResourceDictionary inside the DLL in a new project is simple:
  • Open or create a WPF Application project in Blend or Visual Studio.
  • Go to Project Menu > Add Reference, and open your new DLL file.
  • In the app.xaml (or application.xaml in Visual Studio), add the following code:

      

    2   < Application.Resources >

    3       < ResourceDictionary Source ="/MyExternalAssembly;component/MyResources.xaml" />

    4   </ Application.Resources >

      


Replace the word MyExternalAssembly with the name of your DLL without the ".dll" extension, and MyResources.xaml with your ResourceDictionary name with the extension. So if your DLL is called GlassTheme.dll and your ResourceDictionary is called ThemeFile.xaml, then your code should be:

      

    2   < Application.Resources >

    3       < ResourceDictionary Source ="/GlassTheme;component/ThemeFile.xaml" />

    4   </ Application.Resources >

      


Build your new project and you will see the theme will be applied instantly, however no code is made available and therefore your intellectual property is safe.

The DLL works almost like the XAML files. You can update your code independently from the developers, build a new DLL and send it to them. All the developer needs to do is replace the existing DLL in their project with the new one and everything else is done automatically.

Conclusion
We have gone much farther than we had in our previous installment and we have still only scratched the surface. Remember, WPF allows you to create some amazing user experiences. And what's more is that this is just the first release and future releases will only get more powerful. And it is up to the designer to properly utilize that power to help developers create amazing software applications.
MIX essentials - see it all online
All sessions are available on-demand on our online video platform called Chopsticks. Review sessions you missed or see it all for the first time if you did not make it to the event. In addition to the recorded sessions, all PowerPoint presentations are also available for download (click the Resources tab next to the video).

Follow us on Twitter @mixessentialsbe, we'll keep you posted on any news regarding MIX essentials, Silverlight and Expression.
DreamSpark
The Microsoft DreamSpark student program makes available, at no charge, a broad range of development and design software for download. This includes free access to several commercial products, including Visual Studio 2008 Professional, the Expression suite and XNA Game Studio.
Expression Studio 2 is now available
Download a trial of the new Expression Studio. New features in Blend 2: Silverlight support, vertex animations and an improved user interface with a new split design/XAML view. Expression Web 2: now with PHP support, Photoshop import functionality, improved web standards compliancy, and ASP.NET Ajax server control support and more.
Silverlight rehab video
Folks at the Microsoft Silverlight team in Redmond are quite creative, or are they really in need of rehab? Watch and have fun.
Microsoft