If you haven't been following along and want to learn the techniques then it is best to start at the beginning with Part 1 here.
By now you should be pretty comfortable with editing control templates so I won't give step by step instructions except for techniques I haven't covered, or for tricky template parts.
In this post we are going to have a look at the ProgressBar and Slider controls. This is what the final result will look like:
You can grab the files here.
The ProgressBar Control
The control template for the ProgressBar control looks like this:
The red circle is around the Control Part icon. That icon indicates that the control expects there to be an element in the template called "ProgressBarTrack", and it usually has to be a control of the same type as is used in the default control template - in this case a Border control for "ProgressBarTrack" and a Rectangle element for "ProgressBarIndicator".
A Control Part is critical to a control - the compiled code that manipulates the visual elements expects to find those named parts and won't work without them. Fortunately their names indicate what they do. "ProgressBarTrack" is obviously the track that the progress runs along and "ProgressBarIndicator" is the part that grows to show progress.
For the ProgressBar control, this means that we are restricted to a single Rectangle element to show the progress.
Styling the progress bar is not hard. The points that are possibly worth mentioning are:
- The "ProgressBarTrack" has it's Border and Background brushes bound to the same named properties on the control (template bindings), so change these values on the style, not the "ProgressBarTrack" element. The same goes for the "ProgressBarIndicator" - its Fill brush is bound to the Foreground property on the parent control.
- The "IndeterminateRoot" contains elements that are shown when the "IsIndeterminate" is set to true. The storyboard for the IndeterminateState has an animation that is set to loop Forever. I'll cover this more below.
- The ProgessBar control doesn't have a Disabled state since it doesn't receive focus and is not intended to be interacted with
Of course, there is no reason why you are limited to an angled gradient moving across the bar - you could instead show pixies dancing from side to side, or a conveyor belt dropping toys in a box. Go wild! The only restrictions are that the Control Parts must be kept and used to show the progress when it is not Indeterminate.
The Slider Control
The Slider control is fairly straight forward - the control template is shown on the right. Like the Scrollbar control, there is a vertical and a horizontal template. I have created a separate resource for a Thumb control and assigned it to both the HorizontalThumb and the VerticalThumb. To do this, you would carry out the following steps:
- Select the HorizontalThumb element
- Create a copy of its control template, saving it (for now) as "HorizontalThumbGlassStyle"
- Make your changes to the thumb template
- Exit the Thumb control template, back to the Slider control template
- Use the Advanced Property Options button next to the "Style" property for the "HorizontalThumb" element (in the "Miscellaneous" group) to "Convert to new resource...", and saving it as "ThumbGlassStyle"
There's one more thing to be aware of. The Thumb style resource I created for the slider has a 1 pixel gap between the border of the "Background" element and the "BackgroundGradient" element. I noticed that moving the mouse over the thumb caused the MouseOver state to quickly show, then hide, and then show again. This was because of the gap between the border and the fill - the "Background" Border element has a null brush for it's Background property. Since there was no element of the Thumb under the mouse when it was over the gap, Silverlight considered that the mouse had left the element and put the Thumb into the Normal state. To fix this, I set a solid background color for the top level grid, and set the Alpha for the color to 0. Doing this ensured that there is a solid control under the mouse in the gap, even if it is fully opaque.
Phil many thanks for these series of posts. Found your blog from a Twitter post and being a developer myslef and trying to get better at the design side of things am finding these posts really useful and helpful. Like the way you break things down into their logical elements and build it back up again so I can see how final design is achieved.
ReplyDeleteGavin
Thanks for the feedback Gavin. I'm trying to improve my design skills too and find that writing a series like this is good way to practice the things I've learnt from other people!
ReplyDeleteit's amazing,,
ReplyDelete