Welcome to my fifth Beginners tutorial for Expression Blend & Silverlight.
And this time we will be focusing on ScrollBars, which are a core component of a complicated & nested Control like a ListBox.
My intention in this series of Tutorials, is to make a snazzy/styled ListBox, so we can start to think about Styling an entire application. It won't be a very complicated application, as it will be based on Defwebserver's MVVM File Manager CodeProject article, that he extended on his blog: Enabling Design-Time Data
So how difficult can it be? Not at all, as long as we remember that something like a ListBox is not just one thing. It has multiple components, or Parts!
For example, the Template (Control Template) of a ListBox, consists of multiple elements, and a "Control Part" in the guise of a ScrollViewer.
A Control Part is denoted by the small icon next to the Eye symbol. - (Not sure what it's meant to be?)
Basically, the ScrollViewer "Controls" the Template for this part of the ListBox Control, (which is the overall basic look). And there is more than one Template for this Control, but we will get to that later. First, let us explore this ScrollViewer Control Part, as there is more to see if we delve deeper. And if we look inside the ScrollViewer Template, we will find 3 more Control Parts: ScrollContentPresenter, VerticalScrollBar & HorizontalScrollBar.
So in a ListBox we have nested Controls, & are building a complex Control, from multiple simpler Controls. And you can prove this by finding all these Controls as Assets in their own right. The names I think are self explanatory, and what is obviously apparent: Is that the ScrollBars drive the Content pane scroll function. Now the Content pane has no current Content, & this is because a ContentPresenter is a placeholder, & has no real content of its own. The "Content" for this control is controlled/formatted by another area of the ListBox Control. This is where things get more complicated, but just remember that these Additional Templates, basically describe the look & layout of the Generated Items (Data/Content).
Now I don't want to go steaming into these Additional Templates, & adding complexity, that we can't even see until we get some content! So instead I would like to start by looking at the ScrollBars in the ScrollViewer Template. As we can see these, & almost every complicated Control has a ScrollBar. So I figure we should start with these, as they are quite important...
Again, before commencing this tutorial, I recommend that you read my previous CodeProject tutorials.
I am writing them as a series, & as such this tutorial will presume prior knowledge.
Lesson 1 - "Building Better Buttons" (A beginners guide).
Lesson 2 - "Arcade Button" (How to control the position of elements in a Control Template).
Lesson 3 - "Picture Frame Control" (What is a Control, & why use one?)
Lesson 4 - "The Last Building Buttons" (The WCDoor button, & all 10 buttons for download)
Section 1 - Page Setup & Thumb Template
Section 2 - Applying the ScrollBar Styles
Section 3 - Back to the Vertical ScrollBar
Section 4 - Still the Vertical ScrollBar
Section 5 - Horizontal ScrollBar Styling
Section 6 - Final Adjustments
Section 7 - Source (If I must! )
Section 1 - Page Setup & Thumb Template
Start up a new Silverlight project in Expression Blend, (I'm using Version 4 Beta) & call it "MVVMListBox".
From the Assets menu, drag out a ListBox in the Artboard, & then drag out a ScrollBar, as shown in the image below.
Select the ScrollBar, & choose Edit Template > Edit a Copy.
Name this ScrollBar Style to "MVVMScrollBarStyle" & click OK.
In the Objects and Timeline, there is a HorizontalRoot & a VerticalRoot (which I have expanded).
It is the Vertical root we are interested in, as this is the orientation of the ScrollBar we have. (Are editing).
So what we got in a ScrollBar then? Lots more Control Parts, & 3 Rectangles.
Lets look at the Rectangle's first, & the clue to their function, is looking at the Visual States Manager!
(As well as using the Eye icon to hide, or unhide the element)
In a complicated Control, we can have Visual States at multiple levels of the Control, so keep your eyes open!
Now the ScrollBar I have in mind for this application, does not want these Background elements.
I want the Scroll Bar to float, & these Rectangles will be no use to us, so Delete them all.
With the VerticalRoot selected, the ScrollBar & its layout Grid, will now look like the image below.
Now the only bit that is currently fully visible, is the VerticalThumb element, so let us start with that.
Select the VerticalThumb element, & choose Edit the Template. (But this time, you can choose edit the Current Template).
This is basically because a ScrollBar has to have a Thumb, so one is defined or generated by default.
The VerticalThumb is not a proper Control, available as an Asset, & has no Style of its own.
But it does have Visual States to interact with, as shown in the image below.
Have a look at the various States, & see which ones have Keyframes, as shown in the image below.
Also look at the structure of the Template elements, & notice that we have MouseOver & Pressed elements, that act as overlays.
So let us Delete all the elements in the ThumbVisual Grid, & design a new Thumb from scratch.
Insert a new Rectangle set to Stretch & 0 Margins, in the ThumbVisual Grid, & called it "BGround".
Now Template Bind the Fill to the Background, & the Stroke to the BorderBrush.
But what have we just Template Bound to, if this Control Part has no Style of its own?
It has Template Bound, to it's parent Background & BorderBrush properties.
So if we want to set these colours in the Style, we need to also Template Bind the parent Control Part, to the ScrollBar Style.
The structure or hierarchy is at the top of the Artboard, as shown in the image below.
So Template Bind the VerticalThumb to the ScrollBar Style, & set some Solid Fill colours for BackGround & BorderBrush in the Style.
Go back to the BGround element in the VerticalThumb Template, & set a corner Radius of 4, for both X & Y on the Rectangle.
Now duplicate the Rectangle, & rename the new Rectangle to "Texture",
Remove the Stroke & Fill Bindings, & set the Fill to a Linear gradient orientated as shown in the image below.
Make sure the Gradient Stops are white, & add 3 more Gradient Stops at 25, 50 & 75 on the Ribbon.
Change the Alpha value's to 30%, 80%, 100%, 80%, & 30% on the Ribbon, as shown in the image below.
Now set the element Opacity to 60%, & depending on the colours you picked in the ScrollBar Style, you will have something like the image below.
Now you might be thinking that we could set this gradient in the Style, for greater flexibility from the Style, but this is trickier when testing colour schemes.
So instead, I believe it is better to generate gradients as an overlay, which we can still tweak in one place like the Style. But instead, it will be defined as a Resource.
Select the Fill of the Texture element, & in the Advanced Properties, choose Convert to New Resource, as shown in the image below.
Name this new Resource to "ScrollBarVerticalTexture" & hit OK. (We will be using this texture again later)
Now select the Texture element, & duplicate it to generate a new element, which we will rename Pressed.
Set the Fill of the Pressed element to a Solid black colour & change the element Opacity to 0%.
Now in the VSM, select the Pressed State, & change the Pressed element Opacity to 20%.
Now go to the MouseOver State, & change the Opacity of the texture element to 80%.
And that is it for the VerticalThumb! But before we see it in action, let us apply it to our ListBox Style.
Section 2 - Applying the Styles
Come out of the ScrollBar Template, & go into the Template for the ListBox.
Name the ListBox Style to "ListBoxStyleMVVM", or something similar..
Then into the ScrollViewer Template, & name this Style to "ScrollViewerStyleMVVM", or something similar.
Select the VerticalScrollBar, choose Edit Template > Apply Resource > MVVMScrollBarStyle.
Now do the same for the HorizontalScrollBar. (Will save time later!)
This has made no visible change to the ListBox, but this is because there is nothing to display or Scroll...
And I could force the ScrollBars to be visible, but the Thumb would still not be visible, as there is no content!
So instead, we will inject some Sample Data into the ListBox to reveal the ScrollBars.
Come out of the ListBox Template, & go to the Data tab in the top left of Blend, as shown in the image below.
Create a sample data source, of type "New Sample Data", name it "MVVMSampleData" & click OK. (Or leave the name as default...)
This will generate a Collection of rubbish data to populate our ListBox & show our ScrollBars.
So drag the Collection from the Data tab onto the ListBox, & with a bit of luck & magic, we should have the image below.
Now the Horizontal ScrollBar is not looking too hot, but we can address that in a minute.
First, let us have a quick look at the Generated Content, which is the Sample Data that we have just populated the ListBox with.
So select the ListBox, & choose Edit Additional Templates > Edit Generated Items > Edit Current.
We don't need to Edit a Copy, as we generated the Current Template when we inserted the Sample Data Source.
In the Objects and Timeline, we should have a StackPanel, as shown in the image below.
Laid out in the StackPanel is the Sample Data, consisting of a TextBlock & a CheckBox.
How we are viewing these Sample Data items, is down to the StackPanel, & it's orientation.
So select the StackPanel, & in the Layout section of the Properties tab, change the Alignment to Horizontal, as shown in the image below.
This should change the layout of the Sample Data, as shown in the image below.
But it is still not quite as I would like, I'd prefer the CheckBox first in the list.
And you might think we need to switch the Sample Data around to do this.
But "No", don't be silly!!! - Expression Blend makes it a lot easier than that!
All we need to do is select the TextBlock element, & drag it below the CheckBox element, as shown in the image below.
This re-orders the structure of the StackPanel, & the CheckBox becomes the first item displayed, as shown in the image below.
That is all I will say for the Generated Items Template for the minute, as I want to finish the ScrollBars!
And by now you probably realised, that I have set this ListBox up, with a ScrollBar next to it that we are actually editing.
(Very similar to how I have shown to do buttons! - The reason is touched upon later...)
So before we head back into the ScrollBar Template, let us setup a Horizontal ScrollBar along the bottom of our ListBox.
Ensuring you are not in any Templates, select the ScrollBar Control, & duplicate it.
Resize the duplicated ScrollBar, & place below the ListBox as shown in the image below.
(Do not rotate it, just drag out to the shape in the image above).
In the Properties tab, change the duplicated ScrollBar's Orientation to Horizontal.
Which should helps sort out the ScrollBar a little, & make it look like the ListBox ScrollBar, as shown in the image below.
Still not right, but we will get to the Horizontal ScrollBar later, let us get back to finishing the VerticalScrollBar!
Section 3 - Back to the Vertical ScrollBar
Select the Vertical ScrollBar again in the Artboard (To the right of the ListBox) and go into the Template.
This time I want to edit the VerticalSmallDecrease, & go into the Template for this Control Part.
This reveals a list of elements that make up the VerticalSmallDecrease, as shown in the image below.
But currently we can only see the Path element, & this is due to the VSM (Visual States Manager).
Play with the various States, & you should notice we have States for MouseOver, Pressed & Disabled.
So with that in mind, let us Delete the lot & start again.
Select the Root, & insert a Rectangle with a corner Radius of 4, for both the X & Y values.
Rename the Rectangle to "BGround" & Template Bind the Fill & Stroke to the parent Control Part.
(Remember that this parent Control Part will now need Binding to the ScrollBar Template Style!)
So with that all linked together, we should look something like the image below. (Depending on your Style colours)
(Notice how I'm playing with the ScrollBar, but the ListBox is automatically updating!) - I love it!
So let us duplicate the BGround element, & set up an overlay texture just like we did for the Thumb.
Rename the duplicated Rectangle to "Texture", & set the Fill to "ScrollBarVerticalTexture" Resource, as shown in the image below.
Remove the Stroke of the Texture element, duplicate it, & rename it to "Pressed".
(Don't worry if it defaults to "Pressed1", Blend just thinks it still has an element by this name in this Control Part).
Set the Fill to black, & the element Opacity to 0%.
Now change to the Pressed State, & set the Opacity of the Pressed element to 20%.
Then in the MouseOver State, change the Opacity of the Texture element to 80%.
With some basic animation now setup, now all we need is an Arrow & a Disabled State.
Lets do the Arrow first, & to keep things simple, we will use/modify the existing Arrow.
Which we deleted from the VerticalSmallDecrease, but still exists in the VerticalSmallIncrease Control Part as a Path.
So copy the Arrow Path element from the VerticalSmallIncrease Control Part, into the VerticalSmallDecrease Control Part.
Rename the Path to "UpArrow", Reset the Margins, & with a bit of luck, you will have the same as the image below.
The UpArrow is the wrong way up, so in the Transform section, Flip the Y axis.
Now duplicate the UpArrow, & set the Fill of this new element to any other colour. (I used red).
Select the UpArrow again, & change the Width & Height to Auto.
In the Artboard, you should hopefully have the same as the image below.
(Remember we are working on the right one of these 2 ScrollBars)
If your having layout problems, check your Margin & Stretch settings!
Now select the smaller red copied Arrow, & set a Scale Transform of 3 for the X axis.
Move the red Arrow down using the arrow keys (Margins), until it looks like the image below.
Now shift select the original black UpArrow (the Pastry), & then the red copied UpArrow (the Cutter).
Then from the Object menu, select Combine > Subtract.
(You may get different results if you right click in the Artboard to do this step)
Undo & repeat the last couple of steps, until you have something like the image below.
Reset the Margins, & change the Width & Height to 10 & 8 pixels respectively.
Next Template Bind the Fill, to the parent Control Part BorderBrush. (Not the Background brush!)
This should hopefully give us an UpArrow, that works for both the ScrollBar, & the ListBox ScrollBar.
It is a bit bold, & we could try placing it under the Texture element, but this would obscure it too much.
Instead, just change the UpArrow element Opacity to 75% to soften it a little.
Now all we need is the Disabled element, & we are finished in the VerticalSmallDecrease Control Part.
So duplicate the Pressed element, & rename it to "Disabled", set the Fill to white & the element Opacity to 0%.
Now in the VSM, go to the Disabled State, & set the element Opacity to 70%.
And that is it for this Control Part, but we now need to do the same for the VerticalSmallIncrease Control Part.
So still in the VerticalSmallDecrease, select all the Control Part elements to the clipboard (Ctrl + C).
Now go to the VerticalSmallIncrease, Delete all the existing elements, & Paste in the clipboard elements.
With all the Pasted elements still selected, Reset the Margins to ensure proper placement.
Select just the UpArrow element, rename it to "DownArrow" & Flip the Y axis.
That should make the VerticalSmallIncrease look like the image below.
The colours are all wrong, because the current parent Control Part, is not Template bound to the ScrollBar Style.
So come out of the Control Part, select the VerticalSmallIncrease & Template Bind the Background & BorderBrush's.
That should fix the colour issues, & the only thing left is the Visual States in the VSM.
(Unfortunately Blend can't really be expected to copy these as well..)
So set up Visual States for MouseOver, Pressed & Disabled, based on the setting we used before.
While you are at it, setup a Duration for the State change of 0.1 seconds to the CommonStates group.
Repeat this Duration for the VerticalSmallDecrease, & the VerticalThumb Control Part Templates.
Run the application (F5) and review your results, as shown in the image below.
Now we have discussed 3 of the 5 Control Parts, it is time for a quick mention on the other 2 Control Parts.
The VerticalLargeDecrease & VerticalLargeIncrease are empty, there is nothing in there except a blank Grid.
But it doesn't mean there couldn't be...
The main reason for these parts, are to define the gap between the Thumb, & the VerticalSmallIncrease/Decrease.
(So that it receives a click event to move the Thumb one page length - A Large Increase/Decrease)
Section 4 - Still the Vertical ScrollBar
We now have all the moving, or interacting components that is required in a ScrollBar.
But we can Style it a bit more, so it looks like the Thumb is sliding along a Rail.
So ensure you are not in a Control Part Template, & select the VerticalRoot, as shown in the image below.
Drag out a Rectangle with no corner Radius, so it fills all the sub-divisions of the ScrollBar Grid.
Rename this Rectangle to BGround, & Template Bind the Fill & Stroke to the ScrollBar Style.
Now set the Margins of the BGround Rectangle to 5 for the Left & Right, & 1 for the Top & Bottom.
That should give you the same as the image below, & be aware we are designing in the right ScrollBar, but looking at the left one as the real Style!
(I'm far more interested in these ScrollBars working at the default setting used by Complex Controls, than a super fat version!)
(And ScrollBars do not often get Scaled or Grow like buttons, so have defined the width/size of this Rail using Margins)
Select the BGround Rectangle, right click & choose Group Into > Grid, & rename the Grid to "Rail".
(Clever old Blend takes the Margins, that were applied to the BGround Rectangle, & instead applies them to the Grid)
In the Objects and Timeline select the Rail Grid, & move it above the 5 Control Parts, as shown in the image below.
Select the BGround element, Duplicate it & rename this new element to "Texture".
Reset the Stroke, set the Fill to the "ScrollBarVerticalTexture" & the element Opacity to 80%.
Now in the VSM change to the MouseOver State, & change the Texture element Opacity to 90%.
Set a Duration of 0.1 seconds for the Visual State change, & run your application!
The last thing is to reduce the size of the VerticalThumb Control Part, which we will do by setting a Margin of 2 on the left & right side.
Run the application again, & then set Margins of 2 to the top & bottom of the VerticalThumb Control Part.
Again run the application, & see that the ScrollBar behaves strangely, when the Thumb goes to the bottom.
See how the VerticalSmallIncrease gets pushed down, & is partially out of picture.
(This is because of the top & bottom Margins we just set, conflict with how much room the ScrollBar thinks it now has)
So we don't want to use Margins on the top & bottom of the Thumb! (Remove them)
Select the VerticalSmallDecrease, & change the bottom Margin of 1 to 3 (bottom only), as shown in the image below.
Then select the VerticalSmallIncrease, & apply a Margin of 3 to the top of this Control Part.
And that is it for the Vertical ScrollBar, now we need to repeat all this for the Horizontal ScrollBar...
Section 5 - Horizontal ScrollBar Styling
Come completely out of the Vertical ScrollBar, & select the Horizontal ScrollBar below the ListBox.
Go into the Template, expand the HorizontalRoot, as well as the VerticalRoot, as shown in the image below.
Remember we are still editing the same ScrollBar Style, that we edited for the Vertical ScrollBar!
(See the Rail Grid in the VerticalRoot for proof)
Delete the 4 Rectangle's in the HorizontalRoot so we can start fresh.
Select the Rail from the VerticalRoot, & place a Copy of it in the HorizontalRoot.
Don't worry about changing the name, but move it up the list order as shown in the image below.
The ScrollBar in the Artboard should look like the image below.
Drag out the Rail_Copy Grid, so that it fill all of the ScrollBar, then set Margins of 1 for the left & right, & 5 for the top & bottom.
The Horizontal ScrollBars should now look like the image below.
(But the gradient is running the wrong way!)
So select the Texture element in the HorizontalRoot, & change the Fill to a Gradient brush.
Using the Gradient Tool, change the orientation as shown in the image below.
If you are sad like me, you can set the values exactly as shown in the image below.
Convert this Gradient Brush to a new Resource, & name it "ScrollBarHorizontalTexture".
Set the Opacity of the Texture element to 90%, for the MouseOver State.
Now go to the VerticalRoot, into the VerticalSmallDecrease & Copy all the elements.
Next go back to the HorizontalRoot, & into the HorizontalSmallDecrease Control Part.
Delete all the existing elements, & Paste in the clipboard elements.
Reset the Margins for all the elements, & with some luck, the Artboard will look like the image below.
The colours are wrong because the parent Control Part, is not Template Bound to the Style, so do that now!
Next select the UpArrow, rename it to "LeftArrow", Reset the applied Transforms (the Flip) & Rotate it 90 degree's.
The LeftArrow is not centred, & this is because the Center Point of the Path needs to be Reset.
(This got messed about then we were cupping Pastry!)
Go to the Center Point, & set values of 0.5 for both the X & Y, as shown in the image below.
(These Center Point corrections, should also be applied to the Vertical Up & Down Arrows).
So try to edit the VerticalSmallDecrease from the Template of the Horizontal ScrollBar, and see what happens...
You will probably end up with something like the image below.
This is because Blend does not have any real values to base the size of this Control Part on, as it is for a Vertical ScrollBar.
And the Template we are in, is for a Horizontal ScrollBar!
You can still change the Center Point to 0.5 for both the X & Y, & repeat for the VerticalSmallIncrease.
Use the Return Scope icon when you are finished, to return to a proper view of the Artboard.
Go to the Horizontal ScrollBar Template, into the HorizontalSmallDecrease Control Part & select the Texture element.
Now change the Fill of the Texture element, to the ScrollBarHorizontalTexture Resource.
This should correct the gradient to run inline with the ScrollBar, as shown in the image below.
All we need to do now is setup the Visual States, & repeat everything we did for the Vertical ScrollBar.
So I will leave you to finish this, doing the HorizontalSmallIncrease, & setting up the size of the Horizontal Thumb.
Don't forget the Visual States & setting Durations for these...
(& you may not need a Margin change for the left of the HorizontalSmallIncrease to space out the Thumb).
And that is it, you have your very own Styled Scroll Bars, that can be plugged in to almost any complex Control.
Section 6 - Final Adjustments (ScrollBars)
Just to finish off the ScrollBar section of the ListBox, let us go to the ListBox, & apply some final Styling to the ScrollBars.
So in the Control Template of the ListBox, select the ScrollViewer & go into its Control Template.
Select the Rectangle, which is the pale blue square at the bottom right of the ListBox, & set the Visibility to Collapsed.
Now select the VerticalScrollBar, & change the Margins to 2 on all sides, then do the same for the HorizontalScrollBar.
Look at the ScrollBar Width's & Height's, & see that they have a fixed size. If you want to change their Width's, then do it here!
(I've changed the Width of my ScrollBars to 22 in the image above)
And I think that is it for this Article/Tutorial, as otherwise it will be huge!!!
Play with the Texture Resources that we created to make the bolder ScrollBars shown in the intro image.
The Arrows, as well as the SmallIncrease/Descrease can also be modified/changed with a little bit of effort in say: Expression Design.
I plan to continue this ListBox tutorial in my next Article, where I will discuss more aspects of the ListBox, so we can continue Styling it!
But ScrollBars are ticked off the list, & should be a useful addition to everyone's Silverlight toolbox - Enjoy!
(Feel free to rename the Resources to suit your need, but I will leave mine as they are until Part2).
The final thing I should mention about Control Parts, is that they are expected, so don't just go deleting them or renaming them. The Control Parts can be seen in the Parts tab.
Cheers & please vote!
Section 7 - Source
Obviously you will learn more if you complete the Tutorial, but for those of you that just want to plug-em in and play, here it is!
Download ListBoxScrollBars.zip - 123.24 KB