Templated Silverlight Rating Control

Date September 10, 2008 @ 2:36 pm in Microsoft, Silverlight

Anyone that has been working with the standard set of controls for Silverlight 2 Beta 2 has been exposed to the concept of template binding and how VisualStateManager (VSM) controls state.   In this example I will build a templated control  to learn how to use VSM, template binding and the ContentControl base class. 

The control I choose to create is a Rating control .  The goal is to display a series of Stars that both visualize an overall average score, and allows a user to submit their own rating.  Here is what the control looks like.



RatingControl

The control is comprised of two components: RatingControl and RatingButton. The RatingControl is derived from ContentControl and can either be given an explicit set of RatingButtons, or can automatically create them based on a user setting. Here are the properties I have chosen to expose in RatingContorl:

  • Max (Int): The number of RatingButtons to display
  • Total (double): The number of votes that have been cast
  • Score (double): The average rating across all  submissions
  • UseIndicators(bool): Determines if we will display indicators for what each star represents.

There are two ways in which you can populate the rating control.  The first is to set the Max property and allow the control to add the appropriate number of children.  This works great if you don’t need to specify an individual Indicator (ToolTip) for each RatingButton.  The second approach is to explicitly add RatingButtons to the content property of the RatingControl.  Here is what that would look like in Xaml.

rating_1

By choosing to have our RatingControl inherent from ContentControl it takes care of giving us the ability to set the children of our Content property.  In this example I am assuming a FrameworkElement derived from Panel (Grid or StackPanel) is placed inside of Content.  This makes it very easy to iterate through the panels children and identify each RatingButton.  The following shows the code I used to make the decisions if I would create my own RatingButtons, or use those specified in the RatingControl.Content element.

rating_2


Since I was allowing this control to be templated, I choose to do this setup in the controls Loaded event handler.  This allows me to set the controls Content property equal to my manually created StackPanel, prior to the controls ApplyTemplate method being executed.  This ensures that any special formatting around the panel is applied after the RatingButtons have been added.

RatingButton

To minimize the amount of code I needed to write for this control I decided to build my RatingButton control on top of the System.Windows.Controls.Primitives.ToggleButton.  If you are not familiar with this control it is a very flexible Button that supports three states (Checked, Uncheked, Null).  This is perfect for my example where I will need my star to be visualizes as either filled, empty or half filled star.

For all extensive purposes I left the ToggleButton alone and only overrode OnToggle, OnMouseEnter and OnMouseDown.  Here is what that code looks like.

rating_3


Since each RatingButton needs to behave as a group, I had to circumvent how the ToggleButton would change visual state, and allow RatingControl to manage this process.  The first method UpdateChecked, simply iterates over each rating button, and based on the Score, determines which ones would be checked.  For my visualization I decide that an average score > N.3, but < N.7 would visualize a half star, where as anything above or below would visualize a full or empty star.  I allow the IsChecked property of ToggleButton to switch to the appropriate visual state (Checked, UnChecked or Intermediate).

In the event that a user is hovering over the rating control, I want to visualize a different color of filled star.  Once again I need to allow the RatingControl to determine which RatingButtons need to react to the hover.  The following demonstrates how I achieved this effect.

rating_4


Since once again we choose to circumvent how the ToggleButton switches state on hover, we must  use VisualStateManger.GotToState to trigger the appropriate state of the RatingButton we are evaluating (MouseOver or Normal).  

To  customize the visualization of the this control you can either edit my default style in Blend 2.5, or you can clone it and make your own changes. The Control template is as simple as I could make it to allow users full control over how the RatingButton icons look, and how the states are visualized. 

Code: Rating.zip

/p>

18 Responses to “Templated Silverlight Rating Control”

  1. topwebbusinesses » Blog Archive » Templated Silverlight Rating Control said:

    [...] Original joel [...]

  2. 2008 September 13 - Links for today « My (almost) Daily Links said:

    [...] outlines her InkPresenter – Staying in the lines findings What do you think to Joel Neubeck’s Templated Silverlight Rating Control? Nikolay Raychev helps us to understand Internationalization / localization in Silverlight Mike [...]

  3. Pages tagged "the primitives" said:

    [...] bookmarks tagged the primitives Templated Silverlight Rating Control saved by 8 others     UchihaItachi2590 bookmarked on 09/13/08 | [...]

  4. Scott McAndrew said:

    Cool, Joel. If I could make one suggestion: When you are trying to set the rating, if the mouse moves outside the bounds of the stars as the user moves the mouse sideways, the mouseover (as it is coded, rightfully) loses and gains focus, making the stars blink. You may want to consider having an invisible rectangle the overall width and height of the star area to make the experience a bit smoother. Cool example either way…

  5. Silverlight Cream for September 12, 2008 -- #367 said:

    [...] Templated Silverlight Rating Control [...]

  6. fred said:

    Great !!!!!
    Very nice and very functional !!
    It works perfect under SL 2 beta 2.
    Sorry, but I didn’t succeeded to upgrade it to the new SL version RC0.
    Did you already do it ?
    if yes, could you publish it ?
    Thanks
    Fred

  7. joel said:

    Since RC0 is only for the Dev community, I was not planning on updating any of my samples until RTM. I will take a look at this sample, and let you know what needs to change. It should be pretty simple, but I have not tested it against RC0 to be sure.

  8. Last night's Silverlight User's Group Meeting said:

    [...] Training in downtown Phoenix last night to eat pizza, network, and hear Joel Neubeck talk about his Templated Silverlight Rating Control. First off, a big Thanks to Interface Technical Training for providing facilities for us and [...]

  9. sachin verma said:

    The whole functionality is good ,but one thing i wnt in this example is that–>
    In this example you will have to make one stackpanel of stars ,i.e they will run only once a time (so that a user can vote only once at a time)

  10. Carlos Zumer said:

    The control is great, but there is something I don`t understand, and is the 2 .design files included in the proyect. I’ve tried to search the web for information about them, but could`t find anything. Can you please explain that a bit?

  11. joel said:

    The design files are created from Microsoft Expression Design. I used them to draw the stars then I exported XAML from Expression Design to import into Blend.

  12. Ricardo Fiel said:

    Great stuff! Can this be used on a commercial website?

  13. joel said:

    By all means….please do.

  14. ewart said:

    Ok, silly question but I’m using a black background and want to have bright white stars when I hover over them, instead of red, and mostly white instead of blue.

    When I change “blue” and “red” in the xaml to my two shades of white however they don’t fill as white? but chaning to any other colours except white seems to work?! e..g green and yellow. What am I missing, something to do with opacity?

    By default they appear light gray if unfilled/unselected on my black background which is sweet.

    I plan to adap this control to also support just a single vote/rate-once type mode.

  15. venugopal said:

    AWESOME……………………………..

  16. clems said:

    Has anyone got it working on a childwindow ?
    The indicator element does not seem to refresh

  17. Kiran said:

    cool stuff can you please tell me how to integrate this with a backend database

  18. Bharat Kumar said:

    Great work……………

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">