The team blog of the Expression Blend and Design
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.
Have you ever imported an image or Illustrator file into Expression Design or Expression Blend then noticed that it seems either bigger or smaller than your original image? In this post I will explain why this occurs as well as point out a few tips you can use to get your images and other assets imported into Design and Blend at the pixel size you expect.
Expression Blend assumes a resolution of 96 pixels per inch (PPI). WPF, Expression Blend and Silverlight all assume one pixel is approximately 1/96th of an inch and therefore use a resolution of 96 PPI. You might be asking yourself why 96 PPI? I've been using 72 PPI for all of my web work. The short answer is that Microsoft has standardized to using 96 PPI. There are many web sites that describe why this decision was made and why the standard for Apple is 72 PPI. I encourage the reader who would like to learn more about this choice to search on 96 PPI in your favorite search engine.
If you work with assets that were saved specifying a resolution other than 96 PPI, Design and Blend will scale the asset to be the same physical size at 96 PPI. For example, an image that is 72 PPI and has a width of 6.667 inches and height of 8.889 inches has a width in pixels of 480 and height of 640. If I wanted to display that same image at a resolution of 96 PPI, it would need to have a width and height in pixels of 640 and 853 respectively. Therefore, if you import a 480 X 640 image into Design or Blend that was originally created at 72 PPI, its actual size after import will be 640 X 853.
The best way to ensure your assets come in at the same pixel size in Design or Blend as they are in your other content generation tools is to use 96 PPI throughout your workflow.
When using Expression Design be sure to select 96 PPI in the File > New dialog.
In addition, you should set your zoom level to Actual Pixels in order to see your content at full size. For 96 PPI this is 133%.
In Photoshop, you can change the stored resolution of an image in the Image Size dialog to 96 PPI. Be sure to uncheck Resample Image.
Unfortunately, Illustrator files are 72 PPI and currently always scale when imported into Design when the document resolution is 96 PPI. In this case, you can get the object back to the desired pixel size by selecting Scale As Percentage from the Transform options popup menu in the Action Bar. Make sure width and height are linked and change either the width or height to 75% (72 / 96 = .75).
Hopefully these tips will help keep the import goblins at bay!
Download the RotaryControl source code
Download the ACControls source code
As promised, in this post I’ll show how to customize the template of the RotaryControl. I wanted to model automobile A/C controls and the result is shown below.
If you want to open and examine the project files as I describe the steps, download the source code and unzip it so that the RotaryControl and ACControls folders are siblings. Then open the ACControls solution in Blend 2 September Preview.
For the button design work I went to see Sam Paye, one of our designers, and he used Expression Design to create the visuals. Knowing that the control template requires three specially-named parts, Sam separated out the graphics into three top-level layers, or groups, each named after a template part. We then exported the graphics as three XAML files and opened those directly in Blend. After drawing out three instances of RotaryControl on the artboard and then making a copy of the template for each, it was very easy to copy all three layers from each XAML file and paste them directly into a Grid at the root of the corresponding template. Because the layer names matched the part names, and the Expression Design graphics were the same size (in pixels) as the Grid at the root of the templates, everything worked like a charm. The control code automatically turned off mouse hit testing on the topmost 'shine' layer and allowed the middle 'dial' layer to rotate in response to mouse gestures.
When you select a RotaryControl, a number of custom properties are listed in the Miscellaneous category of the property inspector. None of the controls are meant to spin freely through 360 degrees: all are constrained, so for each I set RotationIsConstrained to true and CounterClockwiseMostAngle and ClockwiseMostAngle to suitable values. For the leftmost control, the mode control, I set SnapToSnapAngle to true and SnapAngle to 40. For the other two controls I set SnapToSnapAngle to false so that they roll smoothly. When SnapToSnapAngle is false, both SnapAngle and RotationIsAnimated are ignored.
The mode control has five positions, and therefore five values, so I used Blend’s collection editor in the property inspector to enter five strings in the SnapValues property – one to describe each position in clockwise order. I then bound a TextBlock’s Text property to the mode control’s SnapValue property so that the current position is always translated into some meaningful string value beneath the mode control.
I hope you find the RotaryControl, and the example templates given here, of use.
While Blend makes it easy for you to create your own controls, creating your own control may not always be the best solution. In many cases, especially when you want to change how a control looks, styling an existing control may be a better choice. While you can style any control by using Blend's UI, modifying system controls can be time consuming if you are new to WPF and not sure what the consequences of modifying a particular property may be. To make it easier on you, Blend includes a resource dictionary called Simple Styles.xaml that applies an easily-modifiable style to your commonly used system controls.
To use these simple style controls, go to your Asset Library and select Simple Styles under the Controls tab:
You will see the simplified versions of your system controls, and they are just like your system controls...except much easier to style.
The User Guide provides great coverage of how to use simple style controls, so if you need any further information, hit F1 or go to Help | User Guide. In the User Guide, you can find Simple Styles listed under Home | Controls | Working with simple styles, or you can do what I did and just search the User Guide for "simple styles" instead!
Cheers! Kirupa Chinnathambi
This service pack addresses critical issues and expands the XAML export feature to better support the 1.0 release of Silverlight. You can download and install the service pack from the Expression Design web site or the Download Center.
What's new in the Service Pack?
Highlights of XAML Export improvements and fixes
Highlights of other issues fixed
To see a full list of the contents of the service pack and issues fixed see the Knowledge Base article.
The Expression Design team
You probably already know that you can use the Brush Transform tool to transform the fill, stroke, opacity mask, or any other brush that is applied to an object. When you click on the Brush Transform tool with an object with, let's say, a gradient brush applied, a brush transform arrow will appear. You can select the brush transform arrow and easily use your mouse cursor to move, scale, and rotate the brush transform arrow to modify your object's gradient fill:
While using your mouse is straightforward, you do not have a lot of precision. There are transforms that you may want to do such as set the gradient rotation to exactly 45 degrees, scale the brush transform arrow equally, and more.
Luckily, such transforms are possible using your mouse cursor and the Alt and Shift keys on your keyboard. Those two keys, among a few others, are known as keyboard modifiers because you use them in conjunction with other keys or mouse clicks. In this post, I will briefly describe common transforms that you can perform to your brush transform arrow using those keyboard modifiers and your mouse cursor.
When you are scaling your transform arrow, unless you have perfect mouse control, your scaling will usually be accompanied by some rotation. To scale perfectly outward/inward with no rotation, hold down your Shift key while clicking and dragging your brush transform arrow endpoint:
Notice that even though our brush transform arrow was originally in a rotated state, when scaling up with the Shift key pressed, the scaling grew perfectly outward.
When you rotate your brush transform arrow, you are free to set any rotation angle you want. There will be times, though, where you would like to rotate your brush transform to a common fixed value such as 45 degrees, 90 degrees, etc. In those cases, hold down your Shift key while rotating:
When holding down your shift key while rotating, you rotate in fixed intervals of 15 degrees. Be sure to note that it is not fixed intervals of 15 degrees relative to your original rotation angle. It is an absolute 15 degrees in a Cartesian plane starting at 0 degrees and ending at 360. If your transform originally had a rotation of 80 degrees, when increasing your rotation angle, your first interval will occur at 90 degrees and then increase by 15 degrees afterwards.
Any alteration you make to your brush transform's endpoint using your mouse cursor affects only that particular endpoint. If you want to symmetrically move both of the end points, you can do that by holding down your Alt key while manipulating any single end point:
This time, notice that even though you scaled out only one of the endpoints, both of the end points grew outward.
As you can see, a combination of the Alt and Shift modifier keys along with your mouse cursor allows you to more precisely control how you can transform your brushes. With radial gradients, the behavior is also the same, so don't feel as if you are limited to applying these tips to linear gradients only.
While this post focused primarily on the brush transform arrow, the above techniques apply to more general transforms also. For example, scaling an object by holding down both your Shift and Alt keys allows you to evenly scale an object outward without adding any rotation. Exploring some of those scenarios will be saved for another post!