Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

10 Cool Buttons for Download in Expression Blend & Silverlight

4.95/5 (153 votes)
13 Jul 2010CPOL29 min read 2   5.1K  
The WC Door button, covering all the missing skills needed to create the buttons shown in my first tutorial. As well as all 10 buttons for download!

Introduction

Welcome to my fourth beginners tutorial for Expression Blend and Silverlight.

I ask for your vote, as I appear to be the only pure Graphics, or Silverlight styling person on CodeProject.

So you decide if I should be here or not!!!!

10FreeButtons/img21.jpg

This tutorial is to complete all the skills required, to construct all the buttons I have previously shown. And probably my concluding article on the topic of building buttons. Although I have other examples, that would not have shown well as a static image, so did not include them. But these deserve a tutorial of their own, so no promises on this being the last button and Vector Graphic tutorial. There is so much more to enjoy with Expression Blend, and far more complicated and interesting Controls to explore and master, like a ComboBox or ListBox for examples.

I will perhaps add and extend this tutorial, based on the requests I receive. But only within the scope of Buttons!

In my first two tutorials, I initially thought I had covered just about everything needed, to create all the buttons shown. Except for maybe Paths, Paths Operations and Corner Radiuses, which were used in the WC Door button. So I was initially reluctant to do any more button construction tutorials and fearful of just repeating myself. This has turned out not to be the case, so please read on!

Overview

Before commencing this tutorial, I recommend that you read my previous Code Project tutorials.
I am writing them as a series and as such, this tutorial will presume prior knowledge.

Toilet (WC) Door Button (Restroom Button)

Section 1- Making the Base Plate

Set up a new project called WCDoorButton, or something similar.

(Or load up the saved BlankButtonTemplate you saved in the previous tutorial/lesson).

Either way, set up six buttons as I have shown in my previous tutorials.

(Ensure you rename, or make another copy of your "BlankButtonTemplate" project to preserve it).

Select one of the buttons, right click and choose Edit Template > Edit a Copy.

Name this new Style as "WCDoorButton" and apply this Style to the other five buttons.

(Use Return Scope to come out of the Control Template.)

If you loaded the BlankButtonTemplate project, you already have the ArcadeButton Style applied to all your buttons.

Which you could have just renamed to WCDoorButton, rather than create a whole new Style.

You can do this, as well as remove any unwanted Styles in the Resources tab.

So with everything setup, let us begin with a blank button Template, except for the ContentPresenter.

With the Grid element selected, drag out a Rectangle to fill the Template.

Ensure it is set to Stretch and the Margins are Reset.

(Or double click the Rectangle Tool in the tool bar, to insert one with these settings as the default.)

Rename the Rectangle to "BaseBGround", right click and Group into > Grid, rename the Grid to "Base".

Select the BaseBGround element and duplicate it twice.

Rename these to "BaseFace" and "BaseTexture".

10FreeButtons/img6.jpg

These three elements will be all we need, to setup the Base. (The back part of the door lock).

Go to the Style now and set a dark blue for the Background colour.

(The default: #FF1F3B53 (Hex Value) will do fine - Copy and Paste straight into Blend).

Back in the Template, set the Fill of the BaseBGround element, to Template Binding > Background.

Remove the Stroke and then hide the BaseTexture element by clicking on the Eye icon next to it.

Next, select the BaseFace element, remove the Stroke and set the Opacity to 20%.

Now apply a ScaleTransform to the BaseFace element, of 0.95 for both the X and Y axis.

The whole reason for this element, is to simulate the flat face of the Base.

And the tapered edge of the Base, to be simulated, by revealing the element behind around the edge.

10FreeButtons/img7.jpg

(The edge will only be a couple of pixels wide, so not worth applying any gradients effects to accentuate it).

We want this edge detail to be a suitable width for all the button sizes, which we have discussed previously.

So we can control the edge with either: Margins, a ScaleTransform, or Grid dividers.

We also want rounded corners, on the Base Plate, so let us look at this first.

Select the BaseBGround element and in the Appearance section of the Properties tab, set the X and Y Radius to 6.

10FreeButtons/imgB.jpg

This obviously, will apply a 6 pixel corner Radius for all the button sizes.

Which is probably about the right sized Radius in the medium sized buttons, but not largest or smallest.

10FreeButtons/img9.jpg

Once again, we have a property that: Does not Scale!

So how are we going to fix, or address this issue this time?

If you are editing the Control Template of the largest button, set the corner Radius of BaseBGround, to 10 pixels for both X and Y .

(Use lower pixel values, if you are editing the smaller button Control Templates.)

Now right click on the BaseBGround element and choose Path > Convert to Path.

10FreeButtons/9a.jpg

(Keep a close eye on the Artboard and the smaller buttons, see how the corners change.)

All the buttons now have a proportional corner Radius.

As they have copied their relative proportions from the Control Template we were editing.

Now select the BaseFace element and set the Margins to 1 on all sides, to help the edge spacing of the smallest buttons.

Next, select the BaseFace element and set a corner Radius of 8 pixels for both the X and Y Radiuses.

(We need lower values than we used for the BaseBGround element, because of the ScaleTransform and the Margins.)

Convert the BaseFace element to a Path, just as you did for the BaseBGround element.

Now just to fine tune, change the ScaleTransform on the BaseFace element to 0.97 for both the X and Y axis.

I'm happy with the setting for all the button sizes now, as shown in the image below:

10FreeButtons/imgD.jpg

(Feel free to adjust your setting as you see fit.)

Now select the BaseTexture element, unhide it and remove the Stroke.

Apply the same corner Radiuses you used for the BaseBGround element and then convert it to a Path.

Set the Fill of the BaseTexture element to a Linear Gradient and to a diagonal orientation using the Gradient Tool.

10FreeButtons/imgF.jpg

I like to set the StartPoint to 0,0 and the EndPoint to 1,1 to ensure I'm exactly at 45%.

10FreeButtons/img10.jpg

(Probably over the top for accuracy and an obsessive compulsive disorder, but it makes me happy!).

Set both the Gradient Stops to white and add another 5 Gradient Stops.

Leave the first Gradient Stop at 100% Alpha, set the second to 0% Alpha and repeat along the Ribbon.

10FreeButtons/img11.jpg

With the Gradient Stops adjusted as shown in image above, your Base should look like the image below:

10FreeButtons/img37.jpg

(Don't get carried away with adjusting the Gradient Stops, as most of the Base will be hidden.)

Set the Opacity of the BaseTexture element to 40% and that is the Base finished!

What you should have learnt from the above steps, other than the corner Radius not Scaling.

Is that the Rectangle Tool/Control is "basically" an inherited Control, based on a Path that describes a rectangle.
But it has additional functionality, like the ability to adjust the corner Radius.

(The Border Tool/Control is similar, but has functionality to individually edit individual corner Radius, as well as the individual Edge/Stroke thicknesses).

Section 2 - Screwing the Base Plate Down

Now let us make and position the Screws located in each corner of the Base.

There are a number of ways we can create the Screw heads and some will Scale, while others will not!

Do we want the Screw head detail to be proportional and Scale, or to be more pronounced in the smaller buttons.

The reason I ask, is because the easiest way to created the outer edge of the Screw head...

Would be to set an Ellipse with a Stroke of 1 pixel, but this will not Scale for all the button sizes.

This may be good enough in some situations, but not here. (Or for me!)

So instead, what we really want is to Scale proportionally, but also emphasis the edge in the smaller buttons.

Can we do it? Let us have a go and find out!

Select the Grid element, (Parent of the Base Grid element) and insert a new Grid.

Rename this Grid as "Screw1", ensure it is set to Stretch and the Margins are set to 0.

Now select the Screw1 element and choose Group Into > Grid, rename this Grid to "ScrewLayout".

10FreeButtons/img3.jpg

With ScrewLayout selected, set up Grid dividers as shown in the image below:

10FreeButtons/img4.jpg

(I have set my Grid dividers at 0.2*, 0.6* and 0.2* for both the Column and Row definitions.)

Here is my XAML for the dividers, as shown in the image below:

10FreeButtons/img5.jpg

Now select the Screw1 element and insert a new Ellipse to fill the Screw1 element. (Stretch, with 0 Margins).

Rename this element as Screw1BGround, remove the Stroke and Template Bind the Fill, to the Background of the Style.

Hopefully in the Artboard, you have an Ellipse (Circle) filling the Base Plate, as shown in the image below:

10FreeButtons/img8.jpg

Now select the Screw1 element and using the Selection Tool, resize it to only fill the top left section of the parent Grid.

Now Reset the Margins of the child element (Screw1BGround), to fit within the bounds of its parent.

The Artboard should look like the image below:

10FreeButtons/img13.jpg

Now set a ScaleTransform on the Screw1 element, of 0.6 for both the X and Y axis.

Next insert another Ellipse into the Screw1 element and rename it to "Screw1Texture".

Set the Fill of Screw1Texture to a Radial Gradient, with white Gradient Stops at 90 and 91 on the Ribbon.

Leave the Alpha value of the first Gradient Stop to 100% and set the Alpha value of the second to 0%.

Set the Opacity of the Screw1Texture element to 40% and the Artboard should look like the image below:

10FreeButtons/img14.jpg

Now we have Screw edges that Scale with the button sizes, as well as the ability to soften the edge detail.

So select the Screw1Texture element and change the Alpha value of the Gradient Stop at 91 on the Ribbon, to 30%.

(See how the contrast of the Screw edge is reduced.)

This works great for the largest button, but is lost and washed out in the smallest button.

As we are basically dealing with fractions of a pixel. (Is that possible?)

So how can we enhance this for the smallest button?

(As setting a Margin of 1 to the Screw1Texture, is far too much.)

(If only we could specify a fraction of a pixel - Oh I forget, we can!!!)

Margins do not have to be whole values, we can specify fractions as well!

(Within the bounds of Layout Rounding, which is basically: What to do with fractions of a pixel).

This can lead to off-centred positioning (As Blend and Silverlight does its best to render it).

But this can still work for us and adds a bit of randomness to the Screw heads, which I like. (Why should it be perfect?)

So set the Margins of the Screw1Texture to 0.2 on all sides.

Now set the element Opacity of Screw1Texture to 60%, to make the Screw head standout a bit more.

With a bit of luck when you run your application (F5), the Screw head, should just about be visible in each button size.

10FreeButtons/img15.jpg

Now let us "Nudge" the Screw head over towards the centre of the button.

(But do this more in the smaller button, than in the largest button, but using Margins).

Select the Screw1 element and set a Margin of 1 to the Top and Left only.

10FreeButtons/imgA.jpg

Run your application and review the results.

10FreeButtons/imgB1.jpg

(You may prefer your Screw heads larger than mine).
(But I will leave mine as they are, or at least until I have created the centre parts of the button).

Now let us put a Slot in the Screw heads, which we could do with just a Path with 2 points.

And then set a Stroke thickness, but again this will not Scale...

(It sort of does when combined with a ScaleTransform, but not elegantly, so not discussed here.)

So select the Screw1 element and insert a new Rectangle. (Set to Stretch, with 0 Margins).

Rename this Rectangle to "Screw1Slot", remove the Stroke and set the Fill to Template Binding > Background.

Now set a ScaleTransform on just the X axis to 0.1 and change the element Opacity to 70%.

Job done! But why did I not set a Linear Opacity Mask on the Screw1Texture element, to form the Slot?

(The problem with an Opacity Mask, is that we often cannot see the results in the Blend environment.)

But before we play with the Slot angles, let us generate the other 3 Screws.

Select the Screw1 element and duplicate it using Copy and Paste.

Using the Selection Tool, drag it to the Top Right corner of the parent Grid.

Set the Margins to 1, for both the Top and Right sides.

Repeat these steps for the other 2 Screws, and remember to set the Margins accordingly.

Now rename all the duplicated elements as shown in the image below:

10FreeButtons/imgC.jpg

(Try to ensure good housekeeping and logical naming.)

Select the Screw1 element and in the Transform section, set a Rotation of 35 degree's.

10FreeButtons/imgF1.jpg

Now set suitable angles, for the remaining 3 Screws.

10FreeButtons/img16.jpg

(I have used -60, -40 and 20 degrees)

And that is it for the Screws, except for recapping what we have learnt.

We can specify a fraction of a pixel.

And we can use Margins to "Nudge" things around, tailoring elements that suit different button sizes.

Section 3 - Forming the Lock Face (Pastry Cutting)

To form the Lock Face (Cover) of the door lock, we need to think about the top and bottom cut outs in the Lock Face.

I like to think of this as Pastry Cutting, where we make a Pastry Cutter, that we use on a piece of Pastry.

The Pastry is simply a Circle (Ellipse), but the Cutter is more complex, if we are to make the Path shape below:

10FreeButtons/img12.jpg

(Which is normally the way, as I generally spend more time making the Cutter, than I do the Pastry.)

There are many ways to combine and cut Pastry, and there are many tutorials online for this, covering all the major Vector Packages.

So I won't be covering how to do this, instead Download PastryCutter.zip I created in Expression Design.

Add the "PastryCutter" file to the project, by using Add Existing Item from the Project menu.

Now select the root element named Grid and insert a new Grid, by double clicking on the Grid tool in the left hand tool bar.

(The Margins should be set to 0, and the Alignments set to Stretch.)

Rename this new Grid to LockFace.

Now go to the Projects tab and double click on PastryCutter.xaml to open it.

In the Objects and Timeline, select the Path element and Copy it to the clipboard.

Now go back to the MainPage.xaml, (By clicking at the top of the Artboard.)

Select the LockFace element and Paste in the Pastry Cutter Path.

(You can now delete the PastryCutter.xaml from the Projects tab).

Select the newly pasted Path element and Reset the Margins to 0.

Before we Scale this Path, to get the proportions correct, let us add a reference object (The Pastry).

Select the LockFace element and double click on the Ellipse tool to insert a new Ellipse.

(Ensure the Margins are 0 and the Alignments are set to Stretch.)

Select the Ellipse and place it behind the Path, by dragging it above it, in the Objects and Timeline.

10FreeButtons/img17.jpg

Set the Fill of the Ellipse to white and ensure the Stroke is removed.

Now apply a ScaleTransform of 0.9 for both the X and Y axis.

Next select the Path element and set a ScaleTransform of 0.68 for the X axis and 0.91 for the Y axis.

That should give you the same as the image below:

10FreeButtons/img18.jpg

(I have set the Opacity of the Path element to 50% for clarity.)

Now "Shift" select, both the Path element and the Ellipse element. (In that order!)

Go to the Object menu and select Combine > Subtract (as shown in the image below):

10FreeButtons/img19.jpg

(The element order selection is important: Select the Cutter, Apply to the Pastry.)

With a bit of magic, you now have a Pastry Ellipse, with the shape of the Cutter Path removed.

10FreeButtons/img20.jpg

(This new "Sweetie" shaped Path, is not working for all the button sizes, but that is a minor Margin issue).

Rename the Path element to "LockFaceBGround", Reset the Margins and set the Fill to Template Binding > Background.

All our buttons should now look like the image below:

10FreeButtons/img1A.jpg

Once again, we need a reference to Scale the Sweetie shape, but we need multiple elements in this style the part of the button.

As such, we should apply the ScaleTransform to the parent object LockFace and subsequently all of its children.

So select the Root element Grid, insert an Ellipse and place it behind the LockFace element.

Remove the Stroke, ensure the Fill is white (for clarity) and apply a ScaleTransform of 0.9 for both the X and Y axis.

Now to aid in setting the right ScaleTransform, select the LockFace element and set the Opacity to 50%.

With the LockFace element still selected, set a ScaleTransform in the Y axis, to match the Ellipse behind it.

(I found that a ScaleTransform of 0.666 in the Y axis worked a treat! - No, I am not the Devil, Yet!).

Select the LockFaceBGround element and duplicate it to create a new element, of type Path in the LockFace parent.

Change the Opacity of the LockFace element back to 100% and rename the new duplicated Ellipse to "LockFaceTexture".

Now obviously, we already have a texture effect applied to the Base, so select BaseTexture and convert the Fill to a New Resource.

Rename this New Resource to "WCDoorButtonTexture".

(If you are using Resource Dictionaries with multiple buttons in it, it pays to name tour Resources accordingly.)

Back with the LockFaceTexture selected, change the Fill to this newly created Resource.

Change the element Opacity of LockFaceTexture to 40%, in an effort to reduce the contrast.

But reducing the contrast, makes the Lock Face darker, so duplicate the LockFaceTexture again.

Rename this new element to "LockFaceEdgeOverlay", set the Fill to Radial Gradient.

Change both the Gradient Stops to white and add another at 90 on the Ribbon.

Select the Gradient Stop at 100 on the Ribbon and change the Alpha value to 0%.

Using the Gradient Tool, change the shape to match the Ellipse (Circle) behind.

10FreeButtons/img1C.jpg

For the moment, that is the Lock Face sorted, let us think about the Rotating (Spinning) disc next.

Section 4 - Information Spinner (Engaged/Vacant)

Select the white Ellipse and select Group Into > Grid.

Rename the Grid to "Spinner" and the child Ellipse to "SpinnerBGround".

Reset the ScaleTransform of 0.9 applied to SpinnerBGround back to 1.0.

And set a ScaleTransform of 0.85, to the Spinner Grid element, as well as a Margin of 1 on all sides.

That should space the Spinner nicely within the Lock Face, as shown in the image below:

10FreeButtons/img1D.jpg

We need to now generate four different images for the Spinner.

(An "Engaged", a "Vacant", a Green colour and a Red colour.)

As this tutorial is about Expression Blend and not Vector Graphics, here are the "Vacant" and "Engaged" Paths.

(I want to stop this Tutorial from rambling on...)

Add these 2 Existing Items to the Project. and in the Projects tab, double click on the Engaged.xaml to access it.

Copy the Path element and return to the MainPage, by clicking at the top of the Artboard.

Select the Spinner element in the button Template and Paste the Path element.

Rename this Path element to SpinnerEngagedText, Reset the Margins and set the Width and Height to Auto.

10FreeButtons/img1E.jpg

We will position the SpinnerEngagedText element, with the help of a Grid and then Rotate the parent Grid.

(Without the parent Grid, the Path element would rotate around its own centre, which would not be the centre of the Spinner).

Select the SpinnerEngagedText element, right click and choose Group Into > Grid.

Rename the Grid element to SpinnerEngaged, set up Grid dividers, as shown in the image below:

10FreeButtons/img23.jpg

Position the SpinnerEngagedText element, inside these new RowDefinitions.

I found that RowDefinitions at 0.02*, 0.25* and 0.73* worked for me, as shown in the XAML below:

10FreeButtons/img24.jpg

Now set up some ColumnDefinitions at 0.225*, 0.54* and 0.235*.

10FreeButtons/img25.jpg

(The Column dividers are slightly off centre, to help centre the SpinnerEngagedText element).

Position the SpinnerEngagedText element inside these dividers, so it looks like the image below:

10FreeButtons/img26.jpg

(I have applied a 0.5 degree Rotation on the SpinnerEngagedText element to tweak it a little.)

We need to do the same for the Vacant part of the Spinner, so Copy and Paste the SpinnerEngaged element.

Rename this duplicated Grid to SpinnerVacant and Delete the child Text element.

Select the original SpinnerEngaged element and to move it out the way Rotate it 90 degrees.

(Which should hide it behind the right side of the LockFace.)

Now find the Vacant.xaml file and Copy the Path to the SpinnerVacant Grid (as you did for the Engaged Path).

(You can remove the Vacant.xaml from the Project now).

Rename the Vacant Path element to SpinnerVacantText and position it within the Grid dividers.

10FreeButtons/img28.jpg

Surprisingly, that seems to fit quite well, although the Text is larger than the "Engaged" Text.

(Change the Opacity of the LockFace to 50%, to reveal the "Engaged" Text.)

Change the Row and Column dividers as you see fit and remember to Reset the Margins of the child element.

I will leave mine as it is, other than to Rotate the SpinnerVacantText element -0.5 degrees.

This just leaves us, the Red and Green indicators to consider.

And we can use the LockFace (Pastry), as the basis for these elements.

So select the LockFaceBGround element and use Copy and Paste to make a duplicate in the Spinner Grid.

Rename this new element to "SpinnerRed", Reset the Margins and ensure the Alignments are set to Stretch.

Change the ScaleTransform to 0.95 for the X axis and 0.6 for the Y axis.

Now in the Objects and Timeline, hide the LockFace elements, by clicking on the Eye next to it.

Reset the Fill of SpinnerRed and set the Fill to a Linear Gradient.

Using the Gradient Tool, arrange the arrow, as shown in the image below:

10FreeButtons/img2A.jpg

Change the first Gradient Stop to a Rich Red (#FFD20000) and place it at 49 on the Ribbon.

Set the other Gradient Stop at 50 on the Ribbon and set the Alpha value to 0%.

This should give you the same as the image below:

10FreeButtons/img2B.jpg

Now duplicate the SpinnerRed element, rename it to SpinnerGreen and rotate it -90 degrees.

Change the Red Gradient Stop to a Rich Green (#FF00B400) and that is it for the Spinner.

Unhide the LockFace elements, and review the results, as shown in the image below:

10FreeButtons/img2C.jpg

Now select the Spinner element and Rotate it 90 degrees, Opp's! -90 degrees to show the Engaged states.

(Maybe it would be better to have this work with positive values of Rotation.)

Reset the Rotation back to 0, select the SpinnerEngaged element and change the Rotation to -90 degrees.

Next select the SpinnerRed element and Rotate it 180 degrees.

That should mean, we can now Rotate the Spinner element 90 degree's, to show the Engaged state.

As shown in the image below:

10FreeButtons/img2D.jpg

And that is it for the Spinner. (This time, or at least for the moment.)

Section 5 - Finishing the Face (Centre Pin and Spinner Recess)

Let us start with the Centre Pin, which should be pretty simple.

(I know I constantly spell "Center" wrong, but I'm English, Sorry!)

Select the Root element in the Objects and Timeline, insert a new Ellipse and rename it to "CentrePinBGround".

Set the Fill to Template Binding > Background and remove the Stroke.

Group the CentrePinBGround element into a Grid and rename the Grid to CentrePin.

Set a ScaleTransform on the CentrePin Grid to 0.25 for both the X and Y axis.

(I want the Centre Pin to be quite small and to grow during MouseOver.)

Now insert a new Ellipse into the CentrePin Grid and rename it to CentrePinOverlay.

Set the Fill to a Radial Gradient, with white Gradient Stops at 0, 85 and 100 on the Ribbon.

Leave the Alpha value of the first Gradient Stop at 100%, change the second to 85%, and the third to 40%.

Now set the element Opacity to 60%, and fingers crossed, it should look like the image below:

10FreeButtons/img2E.jpg

Select the CentrePin Grid element again, insert a Rectangle and rename it to "CentrePinSlot".

Set the Fill to Template Binding > Background and remove the Stroke.

Apply a ScaleTransform of 0.1 for the Y axis and set the element Opacity to 60%.

Job done and should look like the image below:

10FreeButtons/img2F.jpg

Now to create a recessed dish area in the Base, that the Spinner can sit in.

(Which needs to sit in front of the Base and behind the Spinner.)

So select the Root element and insert an Ellipse, rename it to DishBGround.

Now group the DishBGround into a Grid and rename the Grid to Dish".

Next in the Objects and Timeline, drag the Dish Grid above the Spinner Grid.

10FreeButtons/img30.jpg

Select the DishBGround element, remove the Stroke and set the Fill to Template Binding > Background. (As usual!)

Now select the Dish element and set a ScaleTransform of 0.9 for both the X and Y axis.

Insert another Ellipse in to the Dish element, remove the Stroke and set the Fill to a Radial Gradient.

Reverse the Gradient Stops, move the white Gradient Stop to 93 on the Ribbon and set the element Opacity to 30%.

And that should be basically it, as shown in the image below:

10FreeButtons/img31.jpg

Section 6 - Final Touches

I have resisted from applying any indication of light direction up until now, as it would be futile until we have all the elements in place.

Also the LockFace needs a little more edge definition, as does the CentrePin.

But I am not here to repeat effects and techniques, that I have shown in previous tutorials.

So I won't be covering these in this tutorial, other than to say:

Try some DropShadow Effects. - The rest is up to you!

(Or check my finished version, if you get stuck!)

Look at the Stroke I have applied to the Lock Face to make the edge stand out a bit.
As well as how I have created the Slot in the Centre Pin

Check out the Shine I have applied to the Spinner and Dish elements. 

Section 7 - Animation (Button States)

Now before I start playing with the VSM (Visual States Manager), let us consider what type of button this is?

It is currently a standard button, but the function of this Control would better suit a Toggle button.

A Toggle button has CheckStates, which allows us to set visual States for Unchecked, Checked and Intermediate.

10FreeButtons/img32.jpg

(For example, a CheckBox also has these 3 CheckStates.)

The first two States, are fairly self explanatory, the button can be in a Pressed, or Not-Pressed State.

But the third Intermediate State is a little more complex and can be considered as Half-Pressed.

(Not completely accurate and before I upset too many developers, remember this is a beginners tutorial.)

Consider that I have a Toggle button on a page that indicates "Yes" or "No".

But because of other options I have selected on the page, "Yes" or "No" may not be appropriate for these options.

If "Yes" or "No" is not applicable for the selected options, I need another State to define "Not Applicable" or "Not Sure".

Hence the Intermediate State! - (And that is my "Noddy" explanation for Designers, on the Intermediate State.)

(You may think that the Disabled State would work, but Disabled and "Not Sure" are completely different.)

So how do we turn this button into a Toggle button? - To be honest, I don't know!

I'm not sure there is a way of simply converting it, not for a Designer anyway.

But there is no real need, as we can just Copy and Paste, all the elements from a Button Template, to a Toggle Button Template.

You could also select the Root element of the Button Template, right click and choose Make Into Control, based on a Toggle Button.

But this will place a Toggle Button, within a Normal Button (resulting in nested Controls).

So Copy the Root element of our current Button Template, come out of the Template and delete all six buttons.

(Do not worry, all our work is still on the Clipboard!)

From the Assets library, place a Toggle Button on the page and edit the Template.

Name the new Style to WCDoorToggleButton and click OK.

Delete everything in the Template, with the exception of the ContentPresenter.

(If at all, we would rather use the ContentPresenter that came with this Template, rather than the one we are Pasting in.)

(As it is already hooked up to the Style with Template Binding.)

Select the Root Grid element and Paste in all the element from the old Template.

You will probably have at the Root, a Grid within a Grid, so Copy and Paste, to arrange as shown.

10FreeButtons/img33.jpg

(We probably won't use the ContentPresenter, but why delete it? You never know?)
(We could also bring it to the front and leave the Content empty in the Style? - You decide!)

Now come back out the Toggle Button Template and using Copy and Paste, set up six buttons just as we had before.

Now for some animation, and this time, we are going to ignore the Pressed State in the VSM.

Instead, we are going to use the Checked State, as the Pressed State.

So go to the Visual States Manager (VSM) tab. (Top Left of Blend - In Layout Mode)

Go to the Checked State and Rotate the Spinner element 90 degrees.

Setup a Duration of 0.5 seconds and run your application (F5).

Hopefully, your WC Door Lock will now, animate between the Vacant and Engaged States.

Now we need to animate the CentrePin to Rotate along with the Spinner.

So in the Checked State, Rotate the CentrePin 90 degrees.

Next go to the MouseOver State and change the CentrePin ScaleTransform from 0.25, to 0.35.

Repeat the above step in the Pressed State, to stop the CentrePin from shrinking during a button press.

Set a Duration of 0.2 second for the above States group and run your application (F5) to review the results.

We could add some EasingFunctions for the 2 different State groups, so go play!

(Look at my finished version to see what I did.)

Moving on, let us consider what if we only wanted the round central part of our button, to accept mouse events?

So that clicking on the Base and associated Screw does not trigger the button.

All we need to do, is turn Off the IsHitTestVisible property for these elements. and their associated children.

So select the Base and in the Advanced Properties of the Common Properties, turn Off the IsHitTestVisible.

10FreeButtons/img35.jpg

Repeat the above step for the ScrewLayout element, run your application to review the results.

Hopefully your Toggle Button will now only accept mouse events in the inner circular area.

Section 8 - Summary

What I hope we have learnt in this tutorial, is not just a repeat of what I have shown before.

Instead I hope you have leant, that good layout and logical naming is important, as the Control becomes more complicated.

I grouped just about everything within a Grid and a Grid is your best friend with regards to Layout.

It keeps everything tidy, as well as providing power (parental control) over the child elements.

If I did not group things logically, I would have to hunt around to make portions of the Control, not IsHitTestVisible.

This is obviously also true, when it comes to animating parts of the Control in the VSM!

So don't be lazy, it will kick you later!!!

Now even thought we have created this button, based on the parameters I have specified.

I would not say it is the finished article, as I also, have just created this from scratch.

(Not copying my existing example - doing it Rolf Harris Style!).

So you will find that my completed example, has been edited and enhanced, based on my own personal taste.

That is it for now and thanks for reading and voting!!!

Cheers!

Section 9 - Source

Below is the link to the whole project, with the buttons within the UserControl.

Below is the list to just the Resource Dictionary, which will be hard to edit unless you place the Styles, back within the UserControl.

Section 10 - Notes

The Plunger button will Scale its plunger depth, based on its size. Where the Arcade button did not.
This is because it user a change in Center Point and a Scale Transform, allowing it to Scale for all button sizes.

The Celtic Cross button, along with the WC button is a Toggle button.

I have used Blur Effects and Drop Shadows, at sizes that work well on average, but not excessive for smaller Scales. Some editing of these Effects based on size, will always be required.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)