The team blog of the Expression Blend and Design
It’s been a while since the last article where I promised to write about all of the behaviors that ship with Expression Blend in greater detail. I’ll try to be more prompt in the future. Today, let’s look at the ControlStoryboardAction and the StoryboardCompletedTrigger.
Storyboards are one of the primary ways you create animations in Silverlight, WPF, and Windows Phone using Expression Blend. Creating a storyboard is fairly easy, but actually using a storyboard such as having it play is not. To help with this, you have the ControlStoryboardAction.
Simply put, the ControlStoryboardAction is an Action that allows you to select a storyboard and specify what you would like to do to it:
Let’s look at some of the properties it contains in greater detail.
When it comes to this behavior, there are only two properties that you need to concern yourself with. They are the ControlStoryboardOption and Storyboard properties.
The ControlStoryboardOption property lists the tasks you would like to perform:
From here you can choose whether you want to play a storyboard, stop it, toggle between play/pause, pause, resume, or jump to the end.
The only missing piece so far is knowing which storyboard to affect. Not to worry, because you specify the storyboard using the aptly named Storyboard property:
This property will list all of the Storyboards your behavior has access to. Once you have selected a Storyboard, you are done!
Another little behavior component we have is the StoryboardCompletedTrigger:
This trigger invokes an Action when a specified storyboard (set via the Storyboard property) has fully run to completion. Of course, because it is a trigger, you can use it with any Action.
Cheers, Kirupa =)
Hi everyone, To follow up on our announcements made today at MIX 09, we are excited to provide a preview of Expression Blend 3:
Expression Blend 3 Preview includes a lot of cool new features, and if you are attending MIX, the sessions we listed in our earlier post will give you a chance to see some of the new features in action. Once the sessions become available online, we will post them on this blog as well. Besides just the sessions, in the upcoming days, weeks, and months, this blog will also provide a detailed look at the various features Expression Blend 3 Preview contains from the various team members who were involved with their design and development.
Send us your Feedback We would also love to hear from you on what you like about our preview and what you would like to see improved. Feel free to comment on the individual blog posts or post on the Expression Blend Forum!
Cheers! Expression Blend Team
Note: The SketchFlow feature demoed at the keynote is not available in this preview, but we do hope to get that feature into your hands in an upcoming release.
Hi everyone, For the past month, all of the feedback and questions about the Deep Zoom Composer (DZC) were posted here on the blog. To make it easier on everyone, we found a better place for you all to post questions, send us feedback, etc. That location is the Deep Zoom Composer forum. If there any questions that you had asked us earlier that we didn’t notice, please re-post that in our forum.
Filtering This is something that many of you have asked us about. We’ve been busy working on the next preview version of Deep Zoom Composer, so we haven’t been able to post an example for you all to use. Thankfully, Wilfred Pinto has done some really nice work with the Deep Zoom technology, and you can see all of his examples (including filtering, clicking on a subimage, etc.) here: http://projectsilverlight.blogspot.com/search/label/Deep%20Zoom
This blog will probably go a bit quiet on Deep Zoom material until we have our next release (soon!), but expect interesting topics on Expression Blend, Expression Design, and other things you all mentioned in the previous post instead.
Cheers! Kirupa :)
Over the next couple of weeks, it seems like a good idea to go over some of the behaviors we shipped as a part of Expression Blend 3. Many of you have mentioned that you would like to learn more about the stock behaviors we ship and how they are used, so this blog will be a good interim solution for that until we properly incorporate your feedback into our future product documentation.
First up on our list is one of my favorite behaviors that we shipped, the GoToStateAction!
What is it? As you know, you have the ability to define and modify your own visual states in your applications:
Having a visual state is only one part of what needs to be done. The other part is actually being able to switch to the visual state at the appropriate time. For predefined visual states that you find in your controls, the mechanism for switching states is built in. For visual states that you create on your own, you will have to provide the logic for switching the visual states yourself.
That is where this behavior comes in. The GoToStateAction allows you to easily switch visual states given an appropriate event using just your Properties Inspector. The following screenshot shows you the standard behaviors UI customized with the properties exposed by GoToStateAction:
Let’s look at some of these properties in greater detail.
Using It Like I mentioned earlier, this behavior primary functionality lies in allowing you to change the visual state. How it does might require some further inspection, so let’s look at the various properties in more detail.
Picking the Visual State The visual state is set via the StateName property. By default, you will see all the states defined in your root scope (ie: UserControl or Window) regardless of where you drag/drop this behavior onto. You can change this by targeting this behavior at another element.
For example, the default target is my UserControl where I have two states defined:
If I were to target another element, such as a Button that contains its own states, the StateName list is populated with those states instead:
I spoke a lot about changing the target that your states come from, so let’s look at the TargetName property where the element you wish to target is actually specified.
Changing the Target If you want to target states that live somewhere else such as another Control or UserControl, you can use the TargetName property to change the element you want to point to. As mentioned earlier, the default value for TargetName is the root scope such as your UserControl or Window.
You can change the default by clicking on the little circular icon in the value editor to visually pick another element from your Artboard or Objects and Timeline panel:
If you are trying to pick something that isn’t easily selectable visually, you can hit the little … button to see a flat listing of all of your elements. That is similar to what you see in the Objects and Timeline panel.
Playing Transitions You can either switch states suddenly, or you can smoothly transition into states. The UseTransitions property is what controls what your behavior will do. By default, the UseTransitions property is checked, but you can uncheck it if you want a sudden switchover to your new state.
Conclusion Hopefully this helped provide you with a summary of the GoToStateAction and how it can be used. If you have any questions, please feel free to comment below.
Cheers! Kirupa :-)
As you probably know, Silverlight and WPF have a runtime piece called the Visual State Manager (or VSM for short). As I’ll describe in this post, VSM and the Expression Blend tooling support for VSM lend a nice clean mental model to the business of visual states and visual state changes for both custom controls and UserControls.
Although chronologically the story begins with the control author, I’ll talk about that aspect later in this post simply because there are more people in the world concerned with the visual stuff than with the logical stuff. The visual aspect begins in Blend, with a set of already-defined visual states organized into groups in the States panel.
You can identify three stages in the design of visual states and transitions. First, the static stage. Here you make each visual state look the way you want it to, and you do so ideally without any thought of transitions. You select a state in the States panel and you change object properties. And speaking of the States panel, this is probably a good time to introduce the idea of state groups.
Visual states are grouped in such a way that a) the states within a state group are mutually exclusive of one another and b) the states contained in any group are independent of the states contained in any other group. This means that one, and any one, state from every group can be applied at the same time without conflict. An example is a check box where the checked states are independent of, and orthogonal to, the mouse states. Changing an object’s property in more than one state within the same group is common practice. For example, you might change a Rectangle’s Fill to different colors in MouseOver, Pressed and Disabled. This works because only one state from the CommonStates state group is ever applied at a time. But changing an object’s property in more than one state group breaks the independent nature of the state groups and leads to conflicts where more than one state is trying to set the same object’s property at the same time. Blend will display a warning icon (with a tooltip containing details) next to any affected state group whenever this conflict situation is detected.
Each state group should contain a state that represents the default state for that group. CommonStates has ‘Normal’, CheckedStates has ‘Unchecked’, and so on. It is a good (and efficient) practice to set objects’ properties in Base such that no changes have to be made in any ‘default’ state. So, for example, you would hide a check box’s check glyph and focus rectangle in Base and then show them in Checked and Focused respectively.
So now you can click through the states to confirm that each looks correct. You can build and run, and test your states, and you might even stop at this stage if you’re happy that the control switches instantly from one state to another. But if instant state switches are not what you want then you can breathe life into your transitions in stage two, the transitions stage. First, add any transitions you want to see, then set transition durations and easing on them, still in the States panel. And again, in very many cases this will be enough for your scenario. What’s interesting for those designers who can stop at this point is that there was no need to open the Timeline and no need to be bothered with the attendant concepts of what a Storyboard is, etc. To keep unnecessary concepts and UI out of your face, by default Blend keeps the Timeline closed when you select a visual state or edit a transition duration. You can of course open it at any time with the Show Timeline button.
Still in the transitions stage, there may be times when you need a property’s value to change during the transition from StateA to StateB but, because of the way StateA and StateB are defined, the property either doesn’t change or doesn’t pass through the desired value. In this case you need to customize that transition. Select the transition and then use the Timeline as normal to define the animations that should take place during the transition.
The last stage is dynamic states. If, for example, you want a blue rectangle to subtly pulse while a control has focus then you need a steady-state animation. I also call them ‘in-state animations’ because the animation happens while you’re ‘in a state’. To do this, just select the state, open the Timeline, and go ahead and keyframe as usual, possibly also selecting the Storyboard and setting repeat behavior and auto reverse.
Now let’s move onto the topic of how states relate to control authoring. Before a designer can begin deciding what states and transitions look like, the control author must decide what states exist. As a control author, your job is not to think about visual states, but logical states. Forget what it looks like; what does it mean? You need to consider all the ways the end user (and possibly other factors such as invalid data) can interact with the control, and from that thinking build out a set of candidate states; and the states are logical at this point because they have no ‘look’. Now’s the time to think about whether your candidate states need factoring. Look for islands of states: closed graphs that don’t link to other states. There are two kinds: orthogonal and nested. Orthogonal islands should be put in their own state group. An example is that of CheckedStates and FocusedStates. There are no transitions between a CheckedStates state and a FocusedStates state, and a control is either checked or not, and focused or not, and there is no dependency between those two aspects. Islands that should be nested have the characteristics that there are no transitions between a StateGroupA state and a StateGroupB state, and the states in StateGroupB are only effective for one state in StateGroupA. For example if StateGroupA contains LoginPageHidden and LoginPageShown, and StateGroupB contains LoginNormal and LoginError, then it’s clear that StateGroupB is only effective during StateGroupA.LoginPageShown. In this case the two state groups are not orthogonal so you may choose not to use state groups. An alternative, and arguably cleaner, design would be to put StateGroupA at one level of hierarchy with StateGroupB defined on a nested control. Another point to bear in mind, related to naming states, is that each state name must be unique for a control type, even across state groups.
When a control initializes, it first has to get itself onto the state graph. This is important. If a control doesn’t do this then it is still in Base after initialization. Base is not a state; it merely represents the control with its local (or ‘base’) property values set, with no states applied. When the mouse pointer first moves over this control it will go to MouseOver but it will go there from Base, so the Normal -> MouseOver transition will not run the first time. This is a subtle bug that the consumer of your control cannot fix by defining Base -> MouseOver, because Base is not a state. So when you author your own templated control or UserControl, you should define a ‘default’ state in each state group. Have the control go to those ‘default’ states when it initializes, and do so with transitions suppressed so that it happens without delay. Once it’s on the state graph, the control is ready for state transitions to occur so now you can implement the event-handlers that trigger the transitions within the state graph.
I hope this post has been useful and has helped clarify some of the less obvious aspects of designing and authoring controls to work well with the Visual State Manager. If you want to see a walkthrough of some of the ideas presented here, you could try my Button styling video.
While default WPF (and Silverlight) projects make it very easy for you to get up and running with your application for a majority of scenarios, often, there are scenarios where you want better control of your application. A good example of this scenario is the Expression Blend source code itself. We perform a number of tasks (for example, displaying a splash screen) before the main application Window is shown to you. For making this happen, we don’t use the App.xaml concept in WPF projects, but instead go with a code generated Application object which gives us better control over how things work. We then load a number of external resource dictionaries that control the look and feel of our application into the Application’s resources.
However, the lack of App.xaml causes issues when you design your application inside Blend. Blend provides a lot of design-time experiences around App.xaml – for example, all resources in App.xaml are always available in all the projects that are referenced from the main project. This is essentially a feature that lets you easily centralize your shared resources across control libraries into one location. Another example is that we allow you to link your external resource dictionaries into App.xaml, again, to make sharing of resources easier for you.
If you ever run into this, you can use another feature in Blend to work around this issue. You can include your App.xaml into the project file on a conditional basis such that when the project is loaded inside Blend, you get the normal experience that you are comfortable with. While building your application, though, App.xaml is not included in the build process, so your code continues to work as before (for example, WPF automatically creates an entry point for your application when you build App.xaml, but you might already have an entry point defined in code).
The below sample will show how you can leverage this by just making a couple of lines of edit to your project files. Essentially, the changes to the project boil down the following two lines:
<DesignTime Condition="'$(SolutionPath)'!='' AND Exists('$(SolutionPath)')">true</DesignTime>
…. <ApplicationDefinition Condition="'$(DesignTime)'=='true' AND '$(BuildingInsideVisualStudio)'!='true' AND '$(BuildingInsideExpressionBlend)'!='true'" Include="App.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition>
Download the project files from below:
Hope this helps. If you have any questions, feel free to comment here or on our forums.
Today, we released another update to Deep Zoom Composer, and you can download it from the following location:
NOTE: Be sure to uninstall any earlier versions of Deep Zoom Composer before attempting to install our new version.
Most of the work in this release has been under the hood to fix bugs and usability issues, but we did add a few features that you may find cool to use!
Seadragon Ajax Support One of the biggest changes we made was to revamp our Export UI and provide you with the option of exporting your composition as a Seadragon Ajax project:
New and Improved API Something that we’ve mentioned in the past is that we want to make it easier for all of you to integrate Deep Zoom tiling functionality into your own applications. In the past, you only had access to the command-line tools SparseImageTool.exe and ImageTool.exe.
In this release, we are moving away from the command-line tools and moving to a .NET/managed DLL that you can more easily integrate into your applications. I will be sharing more details on this DLL in a future posting, but all of Deep Zoom Composer now uses this DLL for its internal treatment of tiled images. One nice benefit of this is that you get better reliability and performance when importing and exporting images!
Updated Project Templates In the past, we really haven’t given our project templates much attention. We are changing that with this release with more useable templates for both Silverlight and Seadragon Ajax:
The revised templates contain bug fixes and usability issues that many of you have given us feedback on.
Numerous Bug Fixes We deviated a bit from what we said last time that future releases will focus more on under-the-hood changes. The changes you see today are things that many of you had asked us about, so even though we are continuing to invest in stability and performance, do feel free to send us more suggestions. Some oft-asked features may find their way into a future version.
Thanks To.. As always, each Deep Zoom Composer release is a collaborative effort from individual from across Microsoft. A large part of this release relied on the efforts of Dan Cory, Melinda Minch, Lutz Gerhard, Avi Dunn , and other colleagues in Live Labs!
Cheers! Celso Gomes, Christian Schormann, Janete Perez, Kirupa Chinnathambi
Yesterday night, to coincide with the release of Silverlight 2, we released Expression Blend 2 SP1. You can download it by clicking on the following link:
While Expression Blend 2 allowed you to easily design Silverlight 1 and WPF applications, this service pack extends that support to Silverlight 2 as well. You now have the ability to take advantage of Silverlight 2 features such as control templating / styling, visual state manager, font embedding / subsetting, and more directly within Blend itself.
You can learn more about Expression Blend 2 SP1 from both the Expression Community Site as well as our Expression Products Site where more details are provided.
Cheers! Kirupa & the Expression Blend Team
Last week, to coincide with the release of Expression Blend + SketchFlow RC and Silverlight 3, we updated Deep Zoom Composer as well. You can download it from the link below:
As always, please uninstall all existing versions of Deep Zoom Composer before installing the new version.
This release contains improvements to a handful of the existing features based on feedback many of you have provided us.
Bringing back the Blend / Visual Studio projects for certain templates was one of the changes we made (see earlier post). We also made interacting with the Deep Zoom player smoother by removing the constraints that often led to some odd/jagged zooming and panning. The final change of note has to do with our Exporting where we made it extensible as well as possible for you to create composition-less collection exporting.
The last sentence was quite the mouthful, but instead of elaborating here, we will be elaborating in a series of blog posts what the new Exporting changes are and how to use them.
Cheers! Kirupa & Janete
If you are working with a CTP or Beta of Visual Studio Code Name “Orcas”, you will notice that projects and solutions that are created or edited in Visual Studio Orcas cannot be successfully reloaded inside Expression Blend.
To make it easier to work around this issue, we are making available a utility tool that you can use to configure Expression Blend for Visual Studio Code Name “Orcas”. This tool can also be used with the Expression Blend 2 May Preview.
a) Download and unzip the attachment – BlendConfigurator.zip
b) Run the executable – BlendConfigurator.exe
c) Accept the EULA.
d) Choose the installed location of the version of “Blend.exe” that you want to configure. For example, if you are trying to configure the Blend 2 May Preview, you will find it in the (ProgramFiles)\Microsoft Expression\Blend 1.1 folder.
e) Click on the “Visual Studio Code Name ‘Orcas’” button to configure Expression Blend for Visual Studio “Orcas”.
Please note that uninstalling Orcas after configuring Blend for Orcas will result in Blend not working unless reconfigured for Visual Studio 2005 using this tool.
Content is provided "AS IS" with no warranties and confers no rights.
Yesterday was a busy day, for we released an updated version of Deep Zoom Composer as well! You can download the updated version from the following link:
This version of Deep Zoom Composer presents several under-the-hood changes to improve reliability. We are getting close to wrapping up work on version 1 of this powertoy, so we are focusing on improving our existing features in lieu of adding anything new. Expect to see some details on some of those under the hood changes in the upcoming months.
With that said, that isn’t to say you won’t find anything new in this release. The biggest change is that our project templates now work with the released version of Silverlight 2. Previewing in the browser should just work, and our Deep Zoom upload/sharing service, PhotoZoom, has been updated as well.
The next feature is something pretty minor but one we received a ton of requests from all of you on. That feature is…the ability for you to launch Deep Zoom Composer by double-clicking on the DZPRJ file itself:
As always, if you have any questions or suggestions on what you would like to see in future versions of Deep Zoom Composer, please let us know by commenting either here or on our forums.
Cheers! Celso, Christian, Janete, Kirupa
With WPF, you have several ways of creating animations. A common way is by using Storyboards/keyframes, and you can do that easily using Blend itself. If you are willing to take a trip through the dark side and use code to create your animations, you have the ability to create some really cool effects.
Snow is the big thing during this part of the year in much of the world...except if you live in a place that is too warm to have snow in December. To those of you who can't experience real snow (like me who is spending the holidays here), I decided to create a small application that uses UserControls, some old-fashioned C# code, and a dash of CompositionTarget.Rendering to simulate falling snow on your computer:
Click here to run the application, but if you are unable to run the ClickOnce application, download and extract the source code and use Blend 2 or Visual Studio 2008 to open and run this application instead. Let's look at some interesting bits and pieces of code that make up this application:
CompositionTarget.Rendering When creating animations via code, you need some sort of a loop structure that updates what is displayed on your screen. The loop structure in our case is provided via the CompositionTarget.Rendering event which calls our MoveSnowFlakes event handler each time your scene is drawn/re-drawn:
CompositionTarget.Rendering += new EventHandler(MoveSnowflakes);
CompositionTarget.Rendering += new EventHandler(MoveSnowflakes);
For more information on what the CompositionTarget.Rendering event does, refer to its MSDN documentation page.
Creating the Oscillation
If you observe the snowflakes as they fall, you'll see that they oscillate horizontally. The oscillation effect is provided by the Cosine function which takes a number as its argument:
radians += .5*speed;
cX = Canvas.GetLeft(this) + Math.Cos(.1*radians);
radians += .5*speed;
cX = Canvas.GetLeft(this) + Math.Cos(.1*radians);
The oscillations are possible because Cosine is considered to be a periodic function whose output always falls within -1 and 1.
Setting the Positions
We looked at how we create a loop to update what gets displayed and how the oscillation effect is created. The next thing to look at is how the actual positioning works:
if (cY > stageHeight)
cY = -50;
if (cY > stageHeight)
cY = -50;
Because I am interested in positioning each snowflake precisely, each snowflake is placed inside a Canvas layout control, and the exact position is set using the SetLeft and SetTop attached properties. With this approach, I gain the ability to position my snowflake with exact x/y coordinates, but I do lose the automatic layout functionality WPF provides.
I hope this post helped you to see a new way of creating animations in WPF. Because WPF uses hardware acceleration and provides decent drawing support, feel free to experiment and create far cooler animations than what I have shown above or were able to create in the past with other technologies.
Due to popular demand we have added the clip path editing/animating feature to Blend 2. Clip path editing works for both WPF and Silverlight 1.0 projects. You can download the December Preview to test out the new features! In this post, I will go through some of the interesting things you can do with this feature!
What is a Clipping Path? A clipping path is a path or shape that is applied to another object, hiding the portions of the masked object that fall outside of the clipping path. For example, the following image shows you a separate individual image and text object on the left, but thanks to clipping paths, on the right you have just the image object with everything outside of the Seattle text hidden:
Using a Path Object to Apply a Clipping Path Let's take a quick look at how to use clipping paths in Blend:
The left image below shows the path overlaid on our image, and on the right, you see the image visible through the region created by our path:
Editing a Clipping Path You just saw how to apply a clipping path, so let's next look at how you would edit a clipping path. In Blend 2 you now have all path editing capabilities used to edit regular paths applicable to editing clipping paths as well.
The following image shows you how manipulating the path preserves the overall masking efffect that we expect:
Releasing a Clipping Path You saw how to create a clipping path, and you also saw how to edit a clipping path. Let's look at how to actually release a clipping path. It's pretty straightforward:
Note: In Blend 1 you only had the option of removing the clipping path, and that would remove the original clipping object from the artboard. This behavior has been improved in Blend 2 by allowing you to release the clipping path without removing the clipping object!
Animating a Clipping Path In Blend 2, along with being able to edit clipping paths you can also use the full animation capabilities used to animate regular paths to animate clipping paths as well. You can also take advantage of the structure changes supported by vertex animation.
Let's look at that in greater detail:
As seen in the following image, you can apply vertex animations to clipping paths. This can be used to easily create interactivity such as the “spotlight effect”:
Interop with Design You currently have the ability to import files into Blend created with Expression Design with clipping paths or copy/pasting objects with clipping paths applied from Design->Blend.
In Blend 2 we also support editing/animating of these clipping paths. Below is an example of me creating a clipping path in Expression Design:
To import an object with a clipping path from Expression Design to Blend 2 you can simply copy the element from Design and paste it into a Blend project. Below is an example of an image object from Design pasted into a Blend 2 Silverlight 1.0 project.
Conclusion As you can see you can create a variety of visual and interactive effects by creating, editing, and animating clipping paths in Blend 2. Give the features a try and let us know if you have any feedback!
Happy Blending! Janete Perez
A few hours ago, we released another update to Deep Zoom Composer. Click on the link below to download it:
Some of the major new features outside of the usual bug, performance, and stability changes include Panoramic Stitching and PhotoZoom Upload.
NOTE: Our PhotoZoom Upload functionality inside Deep Zoom Composer is causing some uploads to not fully finish before timing out, and we hope to have a fix for this really soon.
PhotoZoom Upload * To help make uploading and sharing your creations with others easy, Deep Zoom Composer nicely integrates with the Live Labs PhotoZoom service: http://photozoom.mslivelabs.com. When you choose to Export, the default selection will be PhotoZoom:
You can use your Live ID to sign-in. Once you have signed in, you can specify an album name, choose a cover image, and just upload:
Once you have uploaded your contents, you will see a dialog that allows you to browse your newly created album in your browser. For example, the following link shows you a sample project I uploaded directly to PhotoZoom: http://photozoom.mslivelabs.com/Album.aspx?alias=kirupa&album=15
Panoramic Stitching Deep Zoom Composer now allows you to stitch similar images inside the application using some cool technology from Microsoft Research's Interactive Visual Group. Take a series of photos that share similar characteristics, right click on them, and select “Create panoramic photo”:
After a short while (the time depends on the number of images, how large the images are, and how much calculation is needed), you will see a dialog allowing you to specify the part of the image that you would like to save. After you have specified region of image to save, your stitched image will appear on your design surface just like any other image you can interact with:
We hope you like our latest release. This is still a beta/preview release, so if you run into any problems, please feel free to post on our forums.
Cheers! The DZC Team (Celso Gomes, Christian Schormann, Janete Perez, and Kirupa Chinnathambi)
* Edit: If you are receiving a 401 error when attempting to upload to PhotoZoom, please try again in a short while. There may be some temporary glitches as we deal with some issues related to this.
Hi everyone, After a bit of a break, we are currently getting the next preview of Deep Zoom Composer ready. While that is going through the final leg of the release process, I was wondering what you would like to see in future releases of Deep Zoom Composer?
Based on the great feedback many of you have provided on my earlier question of a similar sort, I have no doubt that you all will be forthcoming with your opinions on what works, what doesn’t, and what you like to see in future releases.
Thanks, Kirupa :)
Jeff Kelly is back with Part II of his behaviors triple-feature. This time, he focuses on more details and provides some examples of a simple behavior, trigger, and action - Kirupa
Behaviors and triggers are set on objects in XAML via an attached property, Interactions.Behaviors or Interactions.Triggers respectively. When created via XAML, the IAttachedObject interface is invoked behind-the-scenes to automatically associate your triggers, actions and behaviors with the objects they are attached to in the XAML. It is also possible to call the IAttachedObject members directly from code, although the XAML syntax for these operations is typically sufficient.
( Example XAML snippet of a Trigger and Action )
The heart of the behaviors API is the IAttachedObject interface. This interface provides three things: the ability to attach to a specified object, the ability to detach from any object you may be attached to and a property that provides the object to which the IAttachedObject object is currently attached to. Triggers, action and behaviors all implement IAttachedObject. Additionally, each exposes two virtual functions: OnAttached and OnDetaching, which are called in response to the object being attached or detached to another object. Derived classes typically override these functions to hook/unhook event handlers, initialize state or release resources, and so forth.
A basic behavior has nothing more than what we’ve already described: an OnAttached and OnDetaching virtual and an AssociatedObject property. Depending on the desired behavior, the author may implement their behavior as a black-box, or they may choose to expose relevant properties to configure the operation of a specific instance of a behavior. One additional bit of functionality that is exposed by behaviors and specially tooled by Blend 3 are ICommand properties of behaviors. ICommand properties exposed on behaviors allow users of the behavior a way to interact with a behavior in configurable ways that will be explored in more detail in a future post.
The base class for creating a trigger is the TriggerBase class. The main addition to the basic API that Triggers introduce is the inherited InvokeActions method. A trigger typically hooks up event handlers or initializes some internal mechanism that will be used to determine when to fire (a timer, gesture engine, etc). Once a trigger has determined it is ready to fire, the author simply calls the inherited InvokeActions method and all Actions associated with that trigger will be invoked. This method accepts a parameter as an argument that will be passed to all Actions: this mechanism can be used to pass data between your triggers and your actions, such as EventArgs, or can be set to null and ignored.
Actions have the same basic API extensions as Triggers and Actions, but also require the author to implement the abstract Invoke method. This method is called when the action is invoked, and the functionality of the action should be implemented there. The base class for creating an action is TriggerAction.
One nice component of the API is the differences between Silverlight and WPF are minimal. A behavior written for one platform will need only changes to platform-specific code used in its implementation to compile against the other platform; the behavioral APIs are the same between platforms.
Type Constraints When creating a trigger, action or behavior, you need to specify a type constraint. This will control the types that your type may be attached to and is particularly useful if you are assuming the existence of a specific event or property on your AssociatedObject. The type constraint is specified as a generic type argument provided to the base class in your class definition. For instance, if you want to write an action that only applies on types derived from Rectangle, you would define it as:
class MyRectangleAction : TriggerAction<Rectangle>
Note: Your constraint type must derive from DependencyObject. If you don’t have a specific constraint, you should specify DependencyObject in the generic field of your derivative class definition.
Some Simple Examples To wrap up this post, let’s look at some sample behaviors, actions, and triggers. Let’s start with a simple example of a behavior:
A simple trigger would look as follows:
Finally, here is a simple action:
This post was a mix between concepts and details. In a future post, I will dive into even more detail on how to write some of these behaviors.
Download the source code
The RotaryControl is a sample WPF custom control in a class library project that you can open and build in the Blend 2 September Preview. You can use the control along with your own template and property settings as a base to make many different types of rotary dials and knobs and selectors. Once you’ve built the control, create a new WPF Application in Blend, add a reference to the built dll, then use the Asset Library to add an instance of the control to your scene.
The control comes with a default template which you can copy using the breadcrumb bar:
There are three parts to the template. PART_Background isn’t strictly a part because the control doesn’t actually look for this part. But it’s in the default template so you know where to put your background in correct z order. PART_Dial is important however. If you don’t have an element in your template named PART_Dial then the control won’t know which part of the template you want to be the part that rotates in response to the mouse . The dial part needs to sit in front of the background part in order to get mouse hits. PART_Foreground is optional and it’s the name of any element you wish to sit in front of the dial in z order but not to get mouse hits. In the default template I’ve placed a shiny highlight in the foreground layer but I haven’t bothered to set it to IsHitTestVisible = false. The code in the control will do that for me.
Select your control and look at the custom properties in the Miscellaneous category of the property inspector. If you want the dial to snap to certain angles then set SnapToSnapAngle to true and SnapAngle to the angle increments you want to snap to. By default the dial will rotate without constraint. If you want it to only rotate in the range between 0 and 90 degrees then set RotationIsConstrained to true, CounterClockwiseMostAngle to 0 and ClockwiseMostAngle to 90. You can set any of these latter two values to any positive or negative value but they will be stored internally in the range 0 to 360. RotationIsAnimated only really has an effect when you’re snapping; it controls whether or not the snapping is animated in a spring motion. You can use the Angle property to query the angle at any time.
If you are building a rotary selector such as an automobile air-con knob then you will want to associate some semantic value with each angle at which the dial can be oriented. For instance, MAX A/C is a more useful indication of where the dial is than, say, 270. Use the Values property to define a collection of strings. The Value property will then be set to the first string in Values when Angle is equal to CounterClockwiseMostAngle and it will be set to subsequent strings from the collection as the dial is moved clockwise by each increment of SnapAngle.
CursorAttractsNearestSnap has a useful function if your template is such that the values are shown on the dial itself and the indicator is on the background. In this situation it’s useful for the nearest value to spring to the mouse pointer when the mouse is clicked and while the dial rotates.
Next time I’ll show some fresh templates and property settings for the control to illustrate what it can do.
Hi everyone, To coincide with the official launch of Expression Studio 3, we have released the first final version of Deep Zoom Composer as well. You can download it from the below location:
What’s New This release pulls together a lot of the ideas that we had been previewing to you in bits and pieces for the past releases – some for over a year! The following sections describe a few of them in some detail.
Easily Create Interactive Deep Zoom Experiences The Deep Zoom technology in Silverlight can be used to do a lot more than just allowing you to zoom in on high resolution images. Deep Zoom Composer makes it possible for you to create, without writing a single line of code, interactive content involving slideshows, inline navigation, web links, tooltips, and more.
In our latest release, we really tied a lot of the loose ends together to create something that makes it really easy for you import your images and quickly add some of the functionality described earlier. You can learn more about some of these features by reading Janete’s blog posts on these features: Slideshow Support, Creating Menus, and Adding Links.
Analytics Tracking This release of Deep Zoom Composer enhances the support for analytics tracking we exposed in our earlier release. Specify tracking URLs that will silently get called when you zoom in on an image or region. Don’t worry, we made all of this fairly customizable:
Expect to see us blog more about this feature really soon.
Improved DeepZoomPix Player The enhanced player Deep Zoom Composer uses has been ported over to the online DeepZoomPix service. You can now upload your Deep Zoom creations and view/share them with others while maintaining any interactivity you may have added to your images.
Below is a simple example of a Windows 7 wallpaper slideshow uploaded to DeepZoomPix directly from Deep Zoom Composer. Click on the image to see the example live on the DeepZoomPix site:
Go Further (Easily) with your Exported Content With this release, we made it extremely easy for you to go from having a Deep Zoom composition to something you can edit in Expression Blend or Visual Studio. Based on a lot of your feedback, we expanded our default list of templates to include more templates that contain source files:
The templates with source files range from ones that do everything for you such as our Behaviors and Classic templates, but one of our templates is nothing more than an empty project containing just a simple Silverlight Application + WebSite containing just your exported images.
To learn a bit more about our new exporting features, check out Kirupa’s two blog posts on this topic: Extensible Templates in Deep Zoom Composer and Improved Collection Support in Deep Zoom Composer
Revamped UI One of the first things you may notice by looking at Deep Zoom Composer is the more refined look:
We took quite a number of design cues from the work our excellent designer on Expression Blend, Billy Chow did. We hope these subtle UI changes make it easier (and possibly more fun!) for you to work with your content.
Online Documentation To make it easier for us to provide you with direct access to more frequently updated content, we have decided to point users to our online documentation which can be found here. The documentation on our new features has not been published yet, but it will soon. In the interim, you have the links to blog posts we have written posted above.
Support for Smooth Streaming Smooth Streaming is an extension available to IIS web servers where you can easily stream content using adaptive streaming. Deep Zoom Composer now allows you to export your images into a form that is optimized for use on servers enabled with the smooth streaming technology:
We will continue to blog more about some of these new features, so keep watching this blog for original content or links to content on either of our blogs.
A Big Thanks to You All It wouldn’t be fair to conclude this post without saying how grateful we are to all of you who have provided us with feedback and requests on things you would like to see. You all rock.
Of course, Deep Zoom Composer also wouldn’t be possible without the talented work of some brilliant colleagues spread out across Microsoft’s Israel Innovation Labs, Seadragon, and DeepZoomPix teams:
See you all in our blog comments or on our forums.
Cheers! Kirupa & Janete
As you know, Visual State Manager is a Silverlight 2 (and WPF Toolkit) platform feature that makes it easy to define a control’s visual states and to perform the transitions between states. In the case of a templated control (such as Button, CheckBox, etc) you need only fill in the states advertised by the control (using Blend’s States pane), and the control itself will take care of performing the transitions at the right time. But if you’re writing your own UserControl then you need to add your own states to the control and you also need to know how to handle events and call VisualStateManager.GoToState() to transition between your states. Attached to this blog post is a base class that I hope will get you off to a good start. Basically you can derive your own UserControl from this class and override some methods and hopefully that will have saved you some work.
First, download and extract the StatefulUserControlBase.cs source code file from the following location:
Once you’ve downloaded and extracted the source code file (StatefulUserControlBase.cs) you can try out the following steps.
public partial class CheckBoxUC : BlendHelpers.StatefulUserControlBase
CheckTwoStatesEnum _checkState = CheckTwoStatesEnum.Unchecked;
// Required to initialize variables
protected override void UserControl_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
_checkState = (CheckTwoStatesEnum)(1 - (int)_checkState);
protected override void UpdateState()
You now have a functioning two-state checkbox in the form of a UserControl. All you need to do next is to define the states as you would for the built-in CheckBox control. Naturally you won’t want to reproduce the built-in controls with your own UserControls, but now you know how to extend the base class you’ll be ready to do something more practical.
A completed sample is also provided.
Christian Schormann has written a nice article on SketchFlow, so be sure to check it out at the following link: http://electricbeach.org/?p=145
Cheers! Kirupa :)
While the PathListBox control provides an easy way to lay out items along a path, creating a carousel control that appears 3 dimensional and has smooth scrolling requires additional functionality that we did not have time to do in Expression Blend 4. I’ve created the PathListBoxUtils sample available on CodePlex to provide the tools that make creating a carousel like the one shown below very easy:
Visit the Carousel tutorial to see how to create this example, and you can view all PathListBoxUtils-related tutorials here on .toolbox.
Today, we have released a preview of Expression Blend 2 Service Pack 1 that allows you to create content for the release candidate of Silverlight 2. You can download the Service Pack from the following location:
This Service Pack provides you with all of the functionality you had with our earlier Expression Blend 2.5 June 2008 Preview. Besides allowing you to create new projects for WPF, Silverlight 1, and Silverlight 2 RC, we are also exposing new platform functionality like Font Embedding / Subsetting for Silverlight 2 projects. More on this new functionality in future blog posts.
One thing to note, which is different from how we handled releases in the past, is that Expression Blend 2 SP1 Preview will install on top of Expression Blend 2. This will not be a side-by-side installation. This service pack is also an evolution of Expression Blend 2.5, so there will be no future Expression Blend 2.5 releases.
You can find more information on the FAQ page we have created for Expression Blend 2 / SP1.
Cheers! Kirupa & the Expression Blend Team
Today I wanted to share some game prototyping graphics created in Expression Design. These are useful for would-be game developers who happen to be missing a set of quality graphics and/or people who want sample files that can help them understand basic vector drawing techniques.
For example, the following is something I created using Design:
You can download the files used for the above image here: PlanetCute.design (540k)
Expression Design was built to be familiar to folks that already know how to use a vector drawing tool. However, there are a couple of unique tricks that I use every day that make my life much easier.
Always Work in Pixels I always set up my document units to be pixels (at 96 PPI to be exact!). This dramatically reduces any confusion exporting to XAML. If you want more information on why that is done, read Joanna's blog post.
Set your Grid to 10-pixels and Nudge Increment to 1-pixel All the tiles are built on a grid that is 10 px by 10 px. When you set your nudge increment to 1 pixel a nice trick becomes possible. If you hold down Shift while pressing an arrow key, the object will move 10X the nudge increment. In this case, that happens to be 10 px, the exact size of the our grid. Now, instead of manually dragging elements with grid snapping on, I can use Shift + my arrow keys to move elements around and I’ll be guaranteed that they’ll be aligned with my grid. This is quite useful when making tile graphics for games.
You can change your grid size and nudge increment with the following steps:
Shading with Gradients that use Transparent Stops Most of the 3D shading results are done using gradients that have transparent stops. This simple feature, accessible through the Stop Alpha property on every gradient stop, dramatically increases the usefulness of the old reliable gradient. Here’s an example of how I use gradients with transparent stops to create the tile based shadowing system used by the rest of the tiles.
Download Large (more readable!) Version
This set of graphics is pretty flexible. Be creative. Can you make a platform game? Can you make a role playing game? Or a puzzle game? The possibilities are endless. If you find that the set doesn’t include the exact tiles you need for your rocking game design, it is easy enough to open up the .design file in Expression Design, change some colors, or add some shapes. Voila! New tiles and new characters.
I just added the treasure chest graphic and I'm waiting for someone to bust out the first Silverlight Pirate game. Yarr.
To see what other folks have done with these tiles, stop by my website.
Best wishes, Danc.
One of my favorite controls in WPF is the InkCanvas control. As a child, I've always enjoyed simple line drawings, but I started to draw less and less as I got older because I now had to clean up all of the paper and pencils myself! Recently, I began to get back into line drawings, and unlike using physical mediums like pencils and paper, I began playing with the InkCanvas control in WPF instead. This control is very elegant. You have a working application once you simply insert a InkCanvas control. The InkCanvas becomes your paper, and your mouse cursor becomes your pen or pencil.
Behind its elegance, there is actually a lot of great functionality that you can expose, and I created a simple application (with source) that showcases some of the common things you would want to do with an ink canvas:
( Click here to download the Blend 2 / Visual Studio 2008 Source Files )
In the above application, the code shows you how to change your pencil's stroke size, color, and how to use the eraser functionality. Behind the scenes, when you close your application, everything you draw gets saved to your AppData folder. The next time you run your application again, any doodles you made earlier are displayed again - allowing you to pick up from where you left off. There are also more features that I simply haven't had time to implement, but I may revisit this at a later time and improve what is shown above.
Anyway, I hope this helps. If you have any suggestions on examples you would like to see covered in this blog, feel free to drop a line in the comments and I or the other friendly bloggers might use it to guide the content of our future posts.
Oh, and before I forget, the really cool icons used in the above sample are from Mark James's Silk Icons collection.
Update There was a bug in the version of the code I posted initially. Thanks to fellow colleague Sam Paye for pointing it out. The version posted now is the revised version.
Cheers! Kirupa =)
2.5D (two-and-a-half D) is a way of using 2D objects to give a very convincing illusion of 3D. I’ve provided an implementation that has no lighting, materials, lines or polygons. But it does enable you to locate 2D (that is, flat) objects at x,y,z coordinates and place the camera where you want it. The implementation then projects the objects onto the camera, scaling and translating them appropriately, and handles mouse input to move the camera.
You can see a small example demonstrating this below:
Holding the left mouse button and moving the mouse rotates the camera; holding down Ctrl zooms; holding down Shift adjusts the field of view.
Often, rotation causes an object to come in front of another, in terms of their distance from the camera. So each time it draws the scene, the implementation calculates the distance of each object from the camera and then sorts and draws them from back to front. It also culls (that is, removes from the scene) any object behind the camera. Other frills this implementation has are a kind of depth-of-field effect and a fog effect. The depth-of-field effect can be seen whenever an object gets very close to the camera: in this case its opacity falls off exponentially. The fog effect causes the saturation of distant objects to reduce, and their brightness to increase, so that they appear to be melting into fog or haze.
Anyway, you can download the source for the above project from the following location:
You can use Expression Blend 2 SP1 and Visual Studio 2008 to dive into the app and see how
TwoAndAHalfDUC (the first class in the file TwoAndAHalfDUC.cs) is a UserControl base class from which you can derive your own classes. In that same file you will find the CubeUC class that derives from TwoAndAHalfDUC to provide an example of what to do. All you need to do is provide an override of the InitializeSprites method that creates and initializes a number of TwoAndAHalfDSprite objects.
The base class always draws the sprites as colored circles (and of course it does this from any viewing angle so the objects behave as spheres would) but you can amend that behavior so that other 2D objects are used. I tried TextBlocks (and scaled them via their RenderTransform) and the result was very interesting.